Json.Net 无法正确反序列化带有前导零的数字.
Json.Net can't correctly deserialize number with leading zeros.
例如 { "number":010 }
识别为 8(因为 010
in 8 base 等于 8
in 10 base)
For example { "number":010 }
recognized as 8 (because 010
in 8 base equal 8
in 10 base)
如果看JsonTextReader.ParseNumber()
就可以看到
long value2 = text2.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text2, 16) : Convert.ToInt64(text2, 8);
如何禁用 base-cast?也许可以替换 JsonTextReader
?
How it possible disable base-cast? Maybe possible replace JsonTextReader
?
由于 JSON 标准不允许前导零,Newtonsoft 似乎决定将 JavaScript 风格的八进制数解析为标准的扩展,请参阅 Json.NET 3.5 第 7 版 - 有史以来最大的版本.此行为当前被硬编码到 JsonTextReader.ParseReadNumber(ReadType readType, char firstChar, int initialPosition)
没有强制严格遵守标准的选项(即在前导零上抛出异常),如下所述:
Since leading zeros are disallowed by the the JSON standard, it would seem Newtonsoft decided to implement parsing of JavaScript-style octal numbers as an extension to the standard, see Json.NET 3.5 Release 7 – Biggest Release Ever Edition. This behavior is currently hardcoded into JsonTextReader.ParseReadNumber(ReadType readType, char firstChar, int initialPosition)
with no option to force strict conformance to the standard (i.e. throw an exception on a leading zero), as is stated in:
作为一种解决方法,您可以使用 JavaScriptSerializer
解析为中间动态对象,然后将其重新序列化为中间 JToken
,然后将该 JToken
反序列化为您的最后一课:
As a workaround, you could use JavaScriptSerializer
to parse to an intermediate dynamic object, then re-serialize that to an intermediate JToken
, then deserialize that JToken
to your final class:
var json = @"{ ""number"":010 }";
var root = JToken.FromObject(new JavaScriptSerializer().DeserializeObject(json)).ToObject<RootObject>();
if (root.Number != 10)
{
throw new InvalidOperationException();
}
使用
class RootObject
{
public int Number { get; set; }
}
您也可以重新序列化为中间 JSON 字符串,但重新序列化为中间 JToken
对于较大的对象应该更有效.
You could also re-serialize to an intermediate JSON string, but re-serializing to an intermediate JToken
should be more efficient for larger objects.
(切换到 DataContractJsonSerializer如果您不需要 Json.NET 的全部功能,则
或 JavaScriptSerializer
也是选项,因为它们都会默默地解析以 10 为基数的前导零的整数.)
(Switching to DataContractJsonSerializer
or JavaScriptSerializer
are also options if you do not need the full functionality of Json.NET, since both will silently parse an integer with a leading zero in base 10.)
另一种选择是分叉您自己的 JsonTextReader
版本和所有相关实用程序,并修复 JsonTextReader.ParseReadNumber()
抛出 JsonReaderException
当 nonBase10
为真时.不幸的是,fork 您自己的 JsonTextReader
可能需要大量的持续维护,因为您还需要 fork 阅读器使用的所有 Newtonsoft 实用程序(有很多)并将它们更新为原始版本中的任何重大更改图书馆.您还可以投票或评论 增强请求 #646 请求严格的整数解析.
Another option would be to fork your own version of JsonTextReader
and all associated utilities, and fix the logic of JsonTextReader.ParseReadNumber()
to throw a JsonReaderException
when nonBase10
is true. Unfortunately, forking your own JsonTextReader
may require substantial ongoing maintenance, since you will also need to fork any and all Newtonsoft utilities used by the reader (there are many) and update them to any breaking changes in the original library. You could also vote up or comment on enhancement request #646 requesting strict integer parsing.
为什么 Newtonsoft 使用八进制语法来解析数字?我的猜测是他们添加了这个功能来处理 整数文字的 JavaScript 语法:
Why did Newtonsoft implement parsing of numbers in octal syntax? My speculation is that they added this functionality to handle numbers formatted in the JavaScript syntax for integer literals:
整数
整数可以用十进制(以 10 为底)、十六进制(以 16 为底)表示,八进制(以 8 为底)和二进制(以 2 为底).
Integers can be expressed in decimal (base 10), hexadecimal (base 16), octal (base 8) and binary (base 2).
前导 0x(或 0X)表示十六进制.十六进制整数可以包含数字 (0-9) 以及字母 a-f 和 A-F.
Leading 0x (or 0X) indicates hexadecimal. Hexadecimal integers can include digits (0-9) and the letters a-f and A-F.
前导 0b(或 0B)表示二进制.二进制整数只能包含数字 0 和 1.
Leading 0b (or 0B) indicates binary. Binary integers can include digits only 0 and 1.
这篇关于json 网络前导零(禁用基本转换)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!