如果整数以前导零开头,为啥 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
在解析时仍然在数字中,因为 02
和 2
只是相同数字的不同表示(如果你强制使用小数)。
如果前导零对您的数据很重要,那么您可能有一个字符串而不是数字。
"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 语法中 - 更容易区分DecimalIntegerLiteral
与 HexIntegerLiteral
和 OctalIntegerLiteral
。 OctalIntegerLiteral
首先。
看这个作品:
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 无效?的主要内容,如果未能解决你的问题,请参考以下文章