如果整数以前导零开头,为啥 JSON 无效?

Posted

技术标签:

【中文标题】如果整数以前导零开头,为啥 JSON 无效?【英文标题】:Why is JSON invalid if an integer begins with a leading zero?如果整数以前导零开头,为什么 JSON 无效? 【发布时间】:2015-02-06 07:39:49 【问题描述】:

我将一些 JSON 文件导入到我的 Parse.com 项目中,但我不断收到错误“无效的键:值对”。

它表明有一个意外的“8”。

这是我的 JSON 示例:


 "Manufacturer":"Manufacturer",
 "Model":"THIS IS A STRING",
 "Description":"",
 "ItemNumber":"Number12345",
 "UPC":083456789012,
 "Cost":"$0.00",
 "DealerPrice":" $0.00 ",
 "MSRP":" $0.00 ",

如果我通过从 "UPC":083456789012, 中删除 0 或将其转换为 "UPC":"083456789012", 来更新 JSON,它将变为有效。

JSON 真的不能接受以0 开头的整数吗,或者有没有办法解决这个问题?

【问题讨论】:

JSON 语法不允许数字以数字 0 开头。您当然可以将数字放在引号中。 一个以零开头的十进制数应该是一个字符串 如果你有一个 0,那么它很可能不是一个整数,而是一个字符标识符。只需将它们视为字符串! 这不是一个十进制数,它是一个 UPC,它是一个分配给特定产品型号的整数。 @AlexK。 另外,描述“UPC”,我们会告诉你是否需要字符串或整数。 【参考方案1】:

前导 0 表示 javascript 中的八进制数。八进制数不能包含 8;因此,该号码无效。 此外,JSON(官方)不支持八进制数,因此 JSON 是无效的,即使数字不包含 8。但有些解析器确实支持它,这可能会导致一些混乱。其他解析器会将其识别为无效序列并抛出错误,尽管他们给出的确切解释可能不同。

解决方案:如果您有一个数字,请不要将其与前导零一起存储。如果您有一个需要前导零的值,请不要将其视为数字,而应将其视为字符串。用引号将其存储起来。

在这种情况下,您的 UPC 为 needs to be 12 digits long,并且可能包含前导零。我认为最好的存储方式是字符串。

不过,这值得商榷。如果您将其视为条形码,将前导 0 视为其不可分割的一部分,那么字符串是有意义的。其他类型的条形码甚至可以包含字母字符。

另一方面。 UPC 是一个数字,它的左侧填充了 0 到 12 位数字这一事实可以被视为显示属性。实际上,如果您通过添加一个额外的 0 将其左填充为 13 位,您就会得到一个 EAN 代码,因为 EAN 是 UPC 的超集。

如果您有金额,则可以将其显示为 € 7.30,而将其存储为 7.3,因此将产品代码存储为数字也是有意义的。

但这个决定取决于你。我只能建议您使用字符串,这是我个人对这些代码的偏好,如果您选择数字,则必须删除 0 才能使其正常工作。

【讨论】:

@DJSrA 这是领先的0 这就是问题所在。 所以可以引用"UPC":"083456789012",如果是UPC条码,不应该解析为int。 嗯,我今天确实学到了一些新东西。谢谢@GolezTrol。 @T.J.Crowder 好点。这是一个可选的扩展,因此在标准中提到,但这是语义。确实一直不鼓励,目前标准禁止使用,所以在 Json 和 JavaScript 中最好避免使用八进制数。 @GolezTrol:哇,你说得对。回去检查一下,ECMAScript 规范的第一版和第二版都列出了 OctalIntegerLiteral,没有任何明显的对冲。我的错!第 3 版弃用它,第 5 版引入严格模式将其删除。【参考方案2】:

JavaScript 中更令人困惑的部分之一是,如果一个数字以 0 开头,而后没有紧跟 .,那么它代表的是八进制,而不是十进制。

JSON 借鉴了 JavaScript 语法,但避免了混淆功能,因此直接禁止带有前导零的数字(除非其后跟 .)。

即使不是这种情况,也没有理由期望 0 在解析时仍然在数字中,因为 022 只是相同数字的不同表示(如果你强制使用小数)。

如果前导零对您的数据很重要,那么您可能有一个字符串而不是数字。

"UPC":"083456789012"

product code 是一个标识符,而不是你用来做数学的东西。它应该是一个字符串。

【讨论】:

感谢您的快速答复。【参考方案3】:

如果一个整数在 JavaScript 中以 0 开头,则它被认为是整数的八进制(以 8 为基数)值,而不是十进制(以 10 为基数)值。例如:

var a = 065; //Octal Value
var b = 53;  //Decimal Value
a == b; //true

【讨论】:

除了它在 JSON 中根本无效...尝试JSON.parse("65") vs JSON.parse("065")【参考方案4】:

正式地说,这是因为 JSON 在其 JSONNumber 生产中使用了 DecimalIntegerLiteral

JSONNumber ::
    -_opt DecimalIntegerLiteral JSONFraction_opt ExponentPart_opt

DecimalIntegerLiteral 只能以0 开头,如果它是0

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits_opt

背后的理由大概是:

在 JSON 语法中 - 重用主要 ECMAScript 语法中的构造。 在主要的 ECMAScript 语法中 - 更容易区分 DecimalIntegerLiteralHexIntegerLiteralOctalIntegerLiteralOctalIntegerLiteral 首先。

看这个作品:

 HexIntegerLiteral ::
     0x HexDigit
     0X HexDigit
    HexIntegerLiteral HexDigit

...

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit

【讨论】:

"如果为 0,DecimalIntegerLiteral 只能以 0 开头",或者在 0 后面有一个小数点和更多数字 @CupawnTae 那么这不是DecimalIntegerLiteral @lexicore 啊,是的,JSONFraction_opt 处理那个位。读得太快了,抱歉:)【参考方案5】:

我认为通过 JSON 发送您的号码的最简单方法是将您的号码作为字符串发送。

【讨论】:

它不是八进制 - 它是一个固定长度的代码,应该被视为一个字符串【参考方案6】:

UPC 应为字符串格式。将来您可能还会获得其他类型的 UPC,例如 GS128 或基于字符串的产品识别码。将您的数据库列设置为字符串。

【讨论】:

以上是关于如果整数以前导零开头,为啥 JSON 无效?的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中获取带有前导零的整数中的位数?

在C中保持前导零[重复]

如何在 PHP 整数中保留前导零 [重复]

为啥我在 Laravel 中为 foreach 提供无效的参数以进行 json 响应?

二进制手表

为啥 json_extract 有效,但 json_extract_scalar 无效?