json网络前导零(禁用基强制转换)


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

例如,{ "number":010 }被识别为8(因为8个碱基中的010等于10个碱基中8)

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

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

怎么可能禁用基础铸造?也许可以取代JsonTextReader

由于JSON标准不允许使用前导零,Newtonsoft似乎决定将JavaScript风格的八进制数解析作为该标准的扩展,请参阅JSON.NET 3.5 Release 7–史上最大版本。这种行为目前被硬编码到JsonTextReader.ParseReadNumber(ReadType readType, char firstChar, int initialPosition)中,没有强制严格遵守标准的选项(即在前导零上抛出异常),如所述

  • 重写Json反序列化一个以零开头的数字作为小数而不是八进制值
  • Int解析无法正常工作#1057
  • 正在反序列化前导为零的数字#924
  • 支持RFC7159解析#646的"严格模式">

作为一种变通方法,您可以使用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()的逻辑,以便在nonBase10为true时抛出JsonReaderException。不幸的是,派生您自己的JsonTextReader可能需要大量的持续维护,因为您还需要派生阅读器使用的任何和所有Newtonsoft实用程序(有很多),并将它们更新为原始库中的任何突破性更改。您也可以对请求严格整数解析的增强请求#646进行投票或评论。

Newtonsoft为什么用八进制语法实现数字解析?我的猜测是,他们添加了这个功能来处理整数文本的JavaScript语法中格式化的数字:

整数

整数可以用十进制(以10为基数)、十六进制(以16为基数)或十六进制表示,八进制(基数8)和二进制(基数2)。

  • 十进制整数由一系列数字组成,不带前导0(零)
  • 整数文字的前导0(零),或者前导0o(或0o)表示它是八进制的。八进制整数只能包含数字0-7
  • 前导0x(或0x)表示十六进制。十六进制整数可以包括数字(0-9)以及字母a-f和a-f。

  • 前导0b(或0b)表示二进制。二进制整数只能包含数字0和1。

相关内容

  • 没有找到相关文章

最新更新