【问题标题】:Json.net loose vs strict type deserializationJson.net 松散与严格类型反序列化
【发布时间】:2012-11-07 15:40:38
【问题描述】:

在我正在进行的项目中,我们开始使用 Json.Net 库。

但是,我刚刚发现 json.net 在字符串类型上是“松散的”。

这是一个例子:

DTO 类

[JsonObject]
public class DTO
{
    [JsonProperty]
    public string type;
}

反序列化

byte[] rawBody = GetBytes(@"{""type"":true}");
using (MemoryStream ms = new MemoryStream(rawBody))
{
    using (StreamReader sr = new StreamReader(ms))
    {
        var serializer = new JsonSerializer();

        return serializer.Deserialize(sr, typeof(DTO));
     }
 }

这会将“type”属性反序列化为“True”。但是,我希望它会失败并抛出异常,因为存在类型不匹配。 如果我在 json 中将 true 替换为 1,它的作用相同。属性“类型”的值为“1”。

问题:

  1. 有没有办法强制执行严格的序列化?

  2. 除了字符串之外,还有其他类型可以像我们在这里看到的那样进行隐式转换吗?

谢谢。

JF

【问题讨论】:

    标签: .net wcf serialization json.net deserialization


    【解决方案1】:

    我想出了一个解决方法。

    虽然它有效,但我不知道这是否是解决我的“问题”的好方法。

    我使用转换器来转换

    这就是我所做的:

    [JsonObject]
    public class DTO
    {
        [JsonProperty]
        public string type;
    }
    

    自定义转换器:

    class JsonStrictConverter<T> : JsonConverter
        {
            public JsonToken[] TokenTypes { get; set; }
    
            public JsonStrictConverter(params JsonToken[] tokenTypes)
            {
                TokenTypes = tokenTypes;
            }
    
            public override bool CanConvert(Type objectType)
            {
                return objectType == typeof(T);
            }
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                if (reader.TokenType == JsonToken.Null)
                {
                    if (objectType.IsValueType)
                    {
                        return Activator.CreateInstance(objectType);
                    }
                    return null;
                }
    
                var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
                return (T)converter.ConvertFromString(reader.Value.ToString());
            }
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                throw new NotImplementedException("The converter '" + this.GetType().Name + "' is not intended to be used when serializing.");
            }
            public override bool CanWrite { get { return false; } }
        }
    

    反序列化:

    XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
    bodyReader.ReadStartElement("Binary");
    byte[] rawBody = bodyReader.ReadContentAsBase64();
    using (MemoryStream ms = new MemoryStream(rawBody))
    {
        using (StreamReader sr = new StreamReader(ms))
        {
            var serializer = new JsonSerializer();
            /* These converter are present to enforce strict data type in the json. */ 
            /* by default, newtonsoft can serialize Numbers as strings, strings as boolean, etc.... */
            serializer.Converters.Add(new JsonStrictConverter<string>(JsonToken.String));
            serializer.Converters.Add(new JsonStrictConverter<bool>(JsonToken.Boolean));
            serializer.Converters.Add(new JsonStrictConverter<short>(JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<ushort>(JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<int>(JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<uint>(JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<long>(JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<ulong>(JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<float>(JsonToken.Float, JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<double>(JsonToken.Float, JsonToken.Integer));
            serializer.Converters.Add(new JsonStrictConverter<decimal>(JsonToken.Float, JsonToken.Integer));
    
            return serializer.Deserialize(sr, typeof(DTO));                    
        }
    }
    

    这种方法中是否缺少任何类型?

    有没有人有更好的解决方案?

    谢谢。

    【讨论】:

      【解决方案2】:

      认为 json.net 处理严格的类型序列化,而且它比 .net json 序列化器快得多。 http://json.codeplex.com

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 2011-09-19
        相关资源
        最近更新 更多