覆盖Json反序列化一个前导零作为小数而不是八进制值的数字

我正在生成一个json对象,

{ "number":0100 } 

当使用Newtonsoft.Json在C#中反序列化此对象时, 0100被视为八进制数,因为前导零。 有没有办法覆盖此function并使其将数字视为十进制整数?

我看过JsonTextReader.ParseNumber() (数字读取的“魔力”发生的方法)。 我会说这不可行。 八进制案例特别处理

 bool flag2 = c == '0' ... 

然后

 long value2 = text2.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text2, 16) : Convert.ToInt64(text2, 8); // Here OCTAL!!! 

我没有找到任何方法来覆盖此方法(除了重写所有在Json解析中执行所有操作的Read()方法)

如果Newtonsoft.Json这样做,那就是一个bug。 根据http://json.org上记录的JSON语法:

除非不使用八进制和hex格式否则数字非常类似于C或Java编号。”

并且语法图不允许数字具有前导非重要零。

RFC 4627第2.4节。 同意:

“不允许使用八进制和hexforms。不允许使用前导零。”

事实上,根据RFC,你对前导零的使用根本不是有效的JSON。


那么,回答你的问题:

有没有办法覆盖此function并使其将数字视为十进制整数?

可能不是。 而且,你不应该这样做。 相反,你应该修复JSON,或者向生成它的人抱怨它不符合要求。

您还应该将此报告为Newtonsoft.Json中的错误。 。 不要打扰。 作者不承认这是一个错误。 我建议切换到正确实现JSON规范的JSON库。


JSON IMPLEMENTERS的建议

JSON规范(两个版本)明确指出不允许使用hex和八进制forms。

如果向JSON解析器添加对hex和/或八进制(或其他非正式“扩展”)的支持,则会添加JSON标准的碎片。 这是不好的。

这也是一个坏主意,因为当非重要前导零被视为八进制标记时,许多最终用户会感到惊讶。 这导致了像这样的问题…其中(我猜)OP的最终用户已被烧毁,并要求他修复>>他的<<代码以正确处理前导零“。

这里的正确行为是严格实现JSON规范,并拒绝具有非重要前导零的任何数字。 (就个人而言,我会为此实现特殊情况错误消息以及“0x …”hexforms。)

你的.net框架是什么?
您可以使用DataContractJsonSerializer对象反序列化该json。
我试过了。 有效。
使用.net 3.5:它位于System.ServiceMode.Web程序集中。
使用.net 4+:它位于System.Runtime.Serialization.Json程序集中。

例:

 [DataContract] public class TestObject { private int _id; private string _name; private decimal _number; [DataMember] public int ID { get { return _id; } set { _id = value; } } [DataMember] public string Name { get { return _name; } set { _name = value; } } [DataMember] public decimal Number { get { return _number; } set { _number = value; } } } 

测试

 private string jsonText = "{\"Id\": 1, \"Name\": \"kanozuki\", \"Number\":\"0100\"}"; TestObject obj = Deserialise(jsonText); public T Deserialise(string json) { DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T)); using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json))) { T result = (T)deserializer.ReadObject(stream); return result; } } 

结果obj.Id:1 obj.Name:kanozuki obj.Number:100