c# - JSON反序列化——String自动转为Int

标签 c# json asp.net-mvc asp.net-web-api json.net

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

JSON:{"id":"4", "name":"a"} C# 模型:int id;字符串名称

最佳答案

这是 Json.NET 的一个特性:当反序列化原始类型时,它会尽可能将原始 JSON 值转换为 objective-c # 类型。由于字符串"4"可以转化为整数,所以反序列化成功。如果你不想要这个功能,你可以创建一个 custom JsonConverter对于检查正在读取的标记是否真的是数字的整数类型(或 null,对于可为 null 的值):

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 不符合您的需要,您可以通过删除检查来更改它。

您可以按如下方式将其直接应用于您的模型:

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

    public string name { get; set; }
}

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

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

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

关于c# - JSON反序列化——String自动转为Int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41783225/

相关文章:

php - JSON数据没有从objective-C插入到mysql数据库中

c# - 使用 ViewModel 从多个表中获取数据?

asp.net-mvc - 在 MVC2 中使用 FluentValidation 与 CaSTLe Windsor 和 Entity Framework 4.0 (POCO)

javascript - 有没有办法获取我的 Stack Exchange 统计数据?

c# - 英语复数/单数变换函数

C# XNA 删除磁贴组

c# - 为什么我的 Azure 中托管的 ASP NET Web 服务没有执行任何操作?

c# - 启动时从角色入口点加载 DataCache

java - jackson 反序列化多态类型

java - HashSet 没有序列化的 java spring roo