Json.net宽松与严格类型反序列化

9

我正在参与的项目开始使用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中用1代替true,它也会做同样的事情。属性“type”的值将是“1”。
问题:
  1. 有办法强制执行严格的序列化吗?
  2. 除了字符串之外,是否还有其他具有隐式转换的类型,就像我们在这里看到的那样?
谢谢。
JF
2个回答

3
我想出了一个解决方法。
虽然它起作用,但我不知道它是否是解决我的“问题”的好方法。
我使用转换器从中进行转换。
这是我所做的:
[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));                    
    }
}

这种方法中是否有任何类型遗漏?

周围是否有更好的解决方案?

谢谢。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接