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

时间:2023-04-24
本文介绍了json 网络前导零(禁用基本转换)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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:

  • 重写 Json 将前导零作为十进制而不是八进制值的数字反序列化.
  • Int 解析无法正常工作 #1057.
  • 反序列化带有前导零的数字#924.
  • 支持严格模式"进行 RFC7159 解析 #646.李>

作为一种解决方法,您可以使用 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() 抛出 JsonReaderExceptionnonBase10 为真时.不幸的是,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).

  • 十进制整数字面量由一串数字组成没有前导 0(零).
  • 整数文字前导 0(零)或前导 0o(或 0O)表示它是八进制.八进制整数只能包含数字0-7.
  • 前导 0x(或 0X)表示十六进制.十六进制整数可以包含数字 (0-9) 以及字母 a-f 和 A-F.

  • Decimal integer literal consists of a sequence of digits without a leading 0 (zero).
  • Leading 0 (zero) on an integer literal, or leading 0o (or 0O) indicates it is in octal. Octal integers can include only the digits 0-7.
  • 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 网络前导零(禁用基本转换)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:Json.NET JSONPath 查询未返回预期结果 下一篇:将两个 JToken 合并为一个

相关文章