在以下代码中:
using Newtonsoft.Json; namespace TestNanDeserialize { public class Number { public float Float; } public class Empty { } internal class Program { private const string testJson = "{float: NaN}"; private static void Main(string[] args) { Succeeds(); Fails(); } private static void Succeeds() { var result = JsonConvert.DeserializeObject<Empty>(testJson); } private static void Fails() { var result = JsonConvert.DeserializeObject<Number>(testJson); } } }
Succeeds()和Fails()生成两个非常不同的调用堆栈:
成功()
Newtonsoft.Json.dll!Newtonsoft.Json.JsonTextReader.ParseNumberNaN() Line 2299 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonTextReader.ParseValue() Line 1572 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonTextReader.Read() Line 381 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(object newObject,Newtonsoft.Json.JsonReader reader,Newtonsoft.Json.Serialization.JsonObjectContract contract,Newtonsoft.Json.Serialization.JsonProperty member,string id) Line 2331 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(Newtonsoft.Json.JsonReader reader,System.Type objectType,Newtonsoft.Json.Serialization.JsonContract contract,Newtonsoft.Json.Serialization.JsonContainerContract containerContract,Newtonsoft.Json.Serialization.JsonProperty containerMember,object existingValue) Line 485 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader,object existingValue) Line 291 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(Newtonsoft.Json.JsonReader reader,bool checkAdditionalContent) Line 167 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonSerializer.DeserializeInternal(Newtonsoft.Json.JsonReader reader,System.Type objectType) Line 823 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader reader,System.Type objectType) Line 802 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject(string value,System.Type type,Newtonsoft.Json.JsonSerializerSettings settings) Line 863 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject<TestNanDeserialize.Empty>(string value,Newtonsoft.Json.JsonSerializerSettings settings) Line 820 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject<TestNanDeserialize.Empty>(string value) Line 757 C# TestNanDeserialize.exe!TestNanDeserialize.Program.Succeeds() Line 26 C# TestNanDeserialize.exe!TestNanDeserialize.Program.Main(string[] args) Line 20 C#
失败()
Newtonsoft.Json.dll!Newtonsoft.Json.JsonTextReader.ReadAsDouble() Line 948 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(Newtonsoft.Json.JsonReader reader,bool hasConverter) Line 2214 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(object newObject,string id) Line 2359 C# Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(Newtonsoft.Json.JsonReader reader,Newtonsoft.Json.JsonSerializerSettings settings) Line 863 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject<TestNanDeserialize.Number>(string value,Newtonsoft.Json.JsonSerializerSettings settings) Line 820 C# Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject<TestNanDeserialize.Number>(string value) Line 757 C# TestNanDeserialize.exe!TestNanDeserialize.Program.Fails() Line 31 C# TestNanDeserialize.exe!TestNanDeserialize.Program.Main(string[] args) Line 21 C#
您可能认为这应该足以进行调试,也许它应该是,但实际上并没有让我明白在所有这些层中应该以不同的方式使用它以使其工作.
编辑:是的,我知道不带引号的NaN不是有效的JSON. Json.Net的一个明确特征是支持NaN.它显然能够反序列化,如上面的代码所示.但是,我不确定它是否可以反序列化为浮点字段.
注意:我已经为此打开了一个缺陷:https://github.com/JamesNK/Newtonsoft.Json/issues/908
解决方法
@H_301_38@ 你的困难的原因是你的 JSON is invalid – 特别是符号NaN需要被引用.即可以将以下JSON反序列化到Number类中:{"float": "NaN"}
以下不能:
{float: NaN}
请注意,有一个设置FloatFormatHandling.Symbol
允许输出NaN而不带引号,因此可能是早期版本的Json.NET能够将非引用的NaN字符串解析为float或double.但目前情况似乎并非如此.见Serializing NaN results in non-JSON compliant text和Json.NET 5.0 Release 1: Serializing NaN and Infinity Floating Point Values.
更新2
我尝试在各种版本的Json.NET中反序列化未加引号的JSON字符串{float:NaN}:
> 8.0.2(当前):失败.
> 7.0.1:成功.
> 3.5:成功.
所以这可能是回归.你可能想要report an issue.
更新
正如@shannon所指出的,Json.NET对JSON标准的扩展存在不一致. JToken.Parse(“NaN”)返回Float类型的JValue,但JsonConvert.DeserializeObject< double>(“NaN”)抛出异常.可以使用这种不一致性来编写处理非引用的NaN字符串的转换器:
public class FloatNanConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(float) || objectType == typeof(float?); } public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = JValue.Load(reader); if (objectType == typeof(float?)) return (float?)value; else return (float)value; } public override bool CanWrite { get { false; } } public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer) { throw new NotImplementedException(); } }