我正在生成一个json对象,
{
"number":0100
}
当使用Newtonsoft.Json在C#中反序列化此对象时,由于前导零, 0100 被视为八进制数。 有没有办法覆盖此功能并使其将数字视为十进制整数?
答案 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