首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JSON反序列化-字符串自动转换为Int

JSON反序列化-字符串自动转换为Int
EN

Stack Overflow用户
提问于 2017-01-22 02:57:02
回答 2查看 28.7K关注 0票数 10

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

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

EN

回答 2

Stack Overflow用户

发布于 2017-01-22 04:57:57

这是Json.NET的一个特性:在反序列化原始类型时,只要有可能,它就会将原始JSON值转换为目标c#类型。由于字符串"4"可以转换为整数,因此反序列化成功。如果您不需要此功能,可以为整型类型创建一个custom JsonConverter,用于检查正在读取的标记是否真的是数字(对于可以为空的值,则为null ):

代码语言:javascript
复制
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不能满足您的需要,您可以通过取消选中它来更改此设置。

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

代码语言:javascript
复制
public class RootObject
{
    [JsonConverter(typeof(StrictIntConverter))]
    public int id { get; set; }

    public string name { get; set; }
}

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

代码语言:javascript
复制
var settings = new JsonSerializerSettings
{
    Converters = { new StrictIntConverter() },
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);

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

票数 24
EN

Stack Overflow用户

发布于 2017-01-22 03:18:57

你所描述的是一个特性,因为大多数人都想要这种行为。我没有检查,但我打赌它使用了类似Convert.ChangeType(strValue, propertyType);的东西,它试图自动从字符串转换为目标的属性类型。

如果你只需要字符串,使用Maksim的解决方案。

如果需要,您的模型还可以包含一个额外的属性来同时具有这两种类型:

代码语言:javascript
复制
public class Model
{
    public int id { get; set; }
    public string idStr => id.ToString();

    public string name { get; set; }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41783225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档