Json.Net 无法正确反序列化带有前导零的数字。
例如{ "number":010 }识别为 8(因为0108 基等于810 基)
如果看JsonTextReader.ParseNumber()你可以看到
long value2 = text2.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text2, 16) : Convert.ToInt64(text2, 8);
Run Code Online (Sandbox Code Playgroud)
怎么可能禁用 base-cast?也许可以更换JsonTextReader?
由于JSON 标准不允许使用前导零,因此 Newtonsoft 似乎决定实现 JavaScript 风格的八进制数的解析作为标准的扩展,请参阅Json.NET 3.5 第 7 版 – 有史以来最大的版本。这种行为目前是硬编码的JsonTextReader.ParseReadNumber(ReadType readType, char firstChar, int initialPosition),没有强制严格遵守标准的选项(即在前导零上抛出异常),如下所述:
作为一种解决方法,您可以使用JavaScriptSerializer解析为中间动态对象,然后将其重新序列化为中间对象,然后将其JToken反序列化为JToken最终类:
var json = @"{ ""number"":010 }";
var root = JToken.FromObject(new JavaScriptSerializer().DeserializeObject(json)).ToObject<RootObject>();
if (root.Number != 10)
{
throw new InvalidOperationException();
}
Run Code Online (Sandbox Code Playgroud)
使用
class RootObject
{
public int Number { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
您也可以重新序列化为中间 JSON 字符串,但重新序列化为中间体JToken对于较大的对象应该更有效。
(如果您不需要 Json.NET 的全部功能,则切换到DataContractJsonSerializer或JavaScriptSerializer也是选项,因为两者都会默默地解析一个以 10 为基数的前导零的整数。)
另一种选择是分叉您自己的版本JsonTextReader和所有相关实用程序,并修复JsonTextReader.ParseReadNumber()抛出JsonReaderExceptionwhennonBase10为真的逻辑。不幸的是,分叉你自己的JsonTextReader可能需要大量的持续维护,因为你还需要分叉读者使用的任何和所有 Newtonsoft 实用程序(有很多),并将它们更新为原始库中的任何重大更改。您还可以对要求严格整数解析的增强请求 #646 进行投票或评论。
为什么 Newtonsoft 用八进制语法实现数字解析?我的猜测是他们添加了这个功能来处理整数文字的JavaScript 语法格式的数字:
整数
整数可以用十进制(基数 10)、十六进制(基数 16)、八进制(基数 8)和二进制(基数 2)表示。
- 十进制整数文字由没有前导 0(零)的数字序列组成。
- 整数文字的前导 0(零),或前导 0o(或 0O)表示它是八进制的。八进制整数只能包含数字 0-7。
前导 0x(或 0X)表示十六进制。十六进制整数可以包括数字 (0-9) 和字母 af 和 AF。
前导 0b(或 0B)表示二进制。二进制整数只能包含数字 0 和 1。
| 归档时间: |
|
| 查看次数: |
2280 次 |
| 最近记录: |