JSON反序列化-字符串自动转换为Int [英] JSON Deserialization - String Is Automatically Converted To Int

查看:1765
本文介绍了JSON反序列化-字符串自动转换为Int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我通过显式地使用Newtonsoft或通过ASP.NET Web Api的模型绑定机制将JSON反序列化为下面的C#对象时,字符串id值将自动转换为int.我希望它会由于类型不匹配而引发异常或引发错误.这是JSON在规范中的工作方式吗?如果没有,如何防止这种自动转换?

When I deseiralize the JSON to the C# object below, either using Newtonsoft explicitly or via the model binding mechanism of ASP.NET Web Api, the string id value is automatically converted to int. I would expect it to throw an exception or raise an error as there is a type mismatch. Is this how JSON is supposed to work in the specs? If not, how can I prevent such an automatic conversion?

JSON:{"id":"4", "name":"a"} C#模型:int id; string name

JSON: {"id":"4", "name":"a"} C# model: int id; string name

推荐答案

这是Json.NET的功能:在反序列化原始类型时,它将尽可能将原始JSON值转换为目标c#类型.由于字符串"4"可以转换为整数,因此反序列化成功.如果您不希望使用此功能,则可以创建自定义JsonConverter 用于检查所读取的令牌是否确实是数字的整数类型(或null,用于可为空的值):

This is a feature of Json.NET: when deserializing a primitive type, it will convert the primitive JSON value to the target c# type whenever possible. Since the string "4" can be converted to an integer, deserialization succeeds. If you don't want this feature, you can create a custom JsonConverter for integral types that checks that the token being read is really numeric (or null, for a nullable value):

public class StrictIntConverter : JsonConverter
{
    readonly JsonSerializer defaultSerializer = new JsonSerializer();

    public override bool CanConvert(Type objectType) 
    {
        return objectType.IsIntegerType();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case JsonToken.Integer:
            case JsonToken.Float: // Accepts numbers like 4.00
            case JsonToken.Null:
                return defaultSerializer.Deserialize(reader, objectType);
            default:
                throw new JsonSerializationException(string.Format("Token \"{0}\" of type {1} was not a JSON integer", reader.Value, reader.TokenType));
        }
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public static class JsonExtensions
{
    public static bool IsIntegerType(this Type type)
    {
        type = Nullable.GetUnderlyingType(type) ?? type;
        if (type == typeof(long)
            || type == typeof(ulong)
            || type == typeof(int)
            || type == typeof(uint)
            || type == typeof(short)
            || type == typeof(ushort)
            || type == typeof(byte)
            || type == typeof(sbyte)
            || type == typeof(System.Numerics.BigInteger))
            return true;
        return false;
    }        
}

请注意,转换器接受像4.00这样的值作为整数.如果不符合您的需要,可以通过删除JsonToken.Float的复选框来更改它.

Note the converter accepts values like 4.00 as integers. You can change this by removing the check for JsonToken.Float if it does not meet your needs.

您可以将其直接应用于模型,如下所示:

You can apply it to your model directly as follows:

public class RootObject
{
    [JsonConverter(typeof(StrictIntConverter))]
    public int id { get; set; }

    public string name { get; set; }
}

或将转换器包含在 JsonSerializerSettings 中以将其应用于所有整数字段:

Or include the converter in JsonSerializerSettings to apply it to all integral fields:

var settings = new JsonSerializerSettings
{
    Converters = { new StrictIntConverter() },
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);

最后,要在Web API中全局应用JSON序列化程序设置,请参见例如

Finally, to apply JSON serializer settings globally in Web API, see for instance here.

这篇关于JSON反序列化-字符串自动转换为Int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆