当我将JSON反本地化为下面的C#对象时,无论是显式使用Newtonsoft还是通过ASP.NET Web的模型绑定机制,字符串id值都会自动转换为int。我预计它会抛出异常或引发错误,因为存在类型不匹配。这是JSON在规范中应该如何工作的吗?如果没有,我如何防止这样的自动转换?
JSON:{"id":"4", "name":"a"} C#模型:int id; string name
发布于 2017-01-22 04:57:57
这是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; }
}或者将转换器包含在JsonSerializerSettings中,以将其应用于所有整型字段:
var settings = new JsonSerializerSettings
{
Converters = { new StrictIntConverter() },
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);最后,要在Web API中全局应用JSON序列化程序设置,请参见例如here。
发布于 2017-01-22 03:18:57
你所描述的是一个特性,因为大多数人都想要这种行为。我没有检查,但我打赌它使用了类似Convert.ChangeType(strValue, propertyType);的东西,它试图自动从字符串转换为目标的属性类型。
如果你只需要字符串,使用Maksim的解决方案。
如果需要,您的模型还可以包含一个额外的属性来同时具有这两种类型:
public class Model
{
public int id { get; set; }
public string idStr => id.ToString();
public string name { get; set; }
}https://stackoverflow.com/questions/41783225
复制相似问题