当我将JSON解除病毒化到下面的C#对象时,无论是显式地使用Newtonsoft还是通过ASP.NET Web Api的模型绑定机制,字符串id
值都会自动转换为int。我希望它会抛出异常或引发错误,因为存在类型不匹配。这是JSON应该如何在规范中工作?如果没有,我该如何阻止这种自动转换?
JSON:{"id":"4", "name":"a"}
C#型号:int id; string name
答案 0 :(得分:10)
这是Json.NET的一个特性:在反序列化基本类型时,它会尽可能地将原始JSON值转换为目标c#类型。由于字符串"4"
可以转换为整数,因此反序列化成功。如果您不想要此功能,可以为整数类型创建custom JsonConverter
,以检查正在读取的令牌是否真的是数字(或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; }
}
的检查。
您可以直接将其应用于您的模型,如下所示:
var settings = new JsonSerializerSettings
{
Converters = { new StrictIntConverter() },
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);
或者将转换器包含在JsonSerializerSettings
中以将其应用于所有整数字段:
count()
最后,要在Web API中全局应用JSON序列化程序设置,请参阅here。
答案 1 :(得分:0)
尝试将C#模型设为字符串,如果这是您最终想要的。
答案 2 :(得分:0)
您描述的是一个功能,因为大多数人都想要这种行为。我没有检查,但我敢打赌它使用像Convert.ChangeType(strValue, propertyType);
这样的东西试图自动从字符串转换为目标的属性类型。
如果您需要它作为字符串,请使用Maksim的解决方案。
如果需要,您的模型还可以包含额外的属性以包含两种类型:
public class Model
{
public int id { get; set; }
public string idStr => id.ToString();
public string name { get; set; }
}