一尘不染

json净前导零(禁用基播)

json

Json.Net无法正确反序列化带有前导零的数字。

例如,{ "number":010 }识别为8(因为0108底等于810底)

如果看JsonTextReader.ParseNumber()你可以看到

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

如何禁用基本广播?也许可以更换JsonTextReader


阅读 279

收藏
2020-07-27

共1个答案

一尘不染

由于JSON标准不允许使用前导零,因此Newtonsoft似乎决定实施JavaScript样式的八进制数字解析作为该标准的扩展,请参阅Json.NET
3.5 Release 7 –
Everest版本
。目前,这种行为已被硬编码为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();
}

使用

class RootObject
{
    public int Number { get; set; }
}

您也可以重新序列化为中间的JSON字符串,但是JToken对于较大的对象,重新序列化为中间的应该更有效。

(如果您不需要Json.NET的全部功能,请切换到DataContractJsonSerializerJavaScriptSerializer,也可以选择这样做,因为两者都将以基数10静默地解析一个以零开头的整数。)

另一个选择是派生您自己的版本的JsonTextReader以及所有相关的实用程序,并修复JsonTextReader.ParseReadNumber()抛出JsonReaderExceptionwhen
nonBase10为true
的逻辑。不幸的是,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的数字。

2020-07-27