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

时间:2015-03-14 10:57:31

标签: c# json serialization json.net deserialization

我正在生成一个json对象,

{
   "number":0100
}

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

3 个答案:

答案 0 :(得分:10)

如果Newtonsoft.Json这样做,那么这是一个错误。根据{{​​3}}中记录的JSON语法:

  

"数字非常类似于C或Java编号,除了不使用八进制和十六进制格式。"

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

http://json.org第2.4节。同意:

  

"不允许使用八进制和十六进制表单。不允许前导零。"

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


所以,回答你的问题:

  

是否有办法覆盖此功能并将其视为十进制整数?

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

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


JSON IMPLEMENTERS的建议

JSON规范(两个版本)明确指出不允许使用十六进制和八进制形式。

如果您将十六进制和/或八进制(或其他非官方"扩展名")的支持添加到JSON解析器,则会添加JSON标准的碎片。这很糟糕。

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

此处的正确行为是严格实施JSON规范,并拒绝具有非重要前导零的任何数字。 (就个人而言,我为此和#34; 0x ..."十六进制形式实现特殊情况错误消息。)

答案 1 :(得分:3)

我已经查看了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()方法之外)

答案 2 :(得分:-1)

你的.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<TestObject>(jsonText);

public T Deserialise<T>(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