是否有任何实际理由为 JSON 键使用带引号的字符串?

Posted

技术标签:

【中文标题】是否有任何实际理由为 JSON 键使用带引号的字符串?【英文标题】:Is there any practical reason to use quoted strings for JSON keys? 【发布时间】:2011-05-11 05:29:17 【问题描述】:

根据 Crockford 的json.org,一个 JSON object 是由 members 组成的,它由 pairs 组成。

每一对都由一个字符串和一个组成,其中一个字符串被定义为:

字符串是零个或多个的序列 Unicode 字符,双包裹 引号,使用反斜杠转义。一种 字符表示为单个 字符串。一根弦很 很像 C 或 Java 字符串。

但实际上大多数程序员甚至不知道 JSON 键应该用双引号括起来,因为大多数浏览器不需要使用双引号。

用双引号将 JSON 括起来有什么意义吗?

有效示例:


  "keyName" : 34

相对于无效:


   keyName : 34

【问题讨论】:

"何必做对了呢?"这种懒惰的想法会导致网站上充斥着无效的标记。在某些浏览器确实需要双引号的情况下,让您的代码面向未来。 "何必做对了呢?" - 如果没有真正的好处,为什么还要费心遵循其他人没有的约定?也许你把懒惰的思维和实用主义混为一谈了。 @Mark - “其他人都没有”......你从哪里得到这个想法? 每个主要平台中内置的 JSON 序列化程序都会正确引用。 @Mark Rogers php json_encode 函数生成有效的 JSON,例如带有双引号的字符串。也许您正在考虑 javascript 中的对象字面量?确实,那些不引用密钥就可以工作,但这不是 JSON。 作为记录,几年前当我发布这个时,我对@JAL 建议的 JSON 和对象文字表示法之间的区别感到困惑。两者的语法非常相似,这最终导致在描述问题时有些混乱。 【参考方案1】:

为什么 JSON 键应该用引号括起来的真正原因在于 ECMAScript 3 标识符的语义。

Reserved words 不能在不带引号的对象文字中用作 属性名称,例如:

(function: 0) // SyntaxError
(if: 0) // SyntaxError
(true: 0) // SyntaxError
// etc...

如果使用引号,则属性名称有效:

("function": 0) // Ok
("if": 0) // Ok
("true": 0) // Ok

自己的 Crockford 在 this talk 中对此进行了解释,他们希望保持 JSON 标准简单,并且不希望对其进行所有这些语义限制:

....

那时我们发现了 未引用的名称问题。事实证明 ECMA Script 3 保留了一个重击 词政策。保留字必须是 引用在关键位置,即 真的很麻烦。当我四处走动 为了将其制定为标准,我 不想把所有的 标准中的保留字, 因为它看起来真的很愚蠢。

当时,我试图说服 人们:是的,你可以写 JavaScript 中的应用程序,它是 实际上要去工作,这很好 语言。那时我不想说, 同时:看看这个 他们做的真是愚蠢的事!所以我 决定,相反,让我们引用 键。 这样我们就不用说 任何人都知道它有多糟糕。

这就是为什么,直到今天,密钥仍被引用 JSON。

...

ECMAScript 第 5 版标准修复了这个问题,现在在 ES5 实现中,即使是保留字也可以不带引号使用,在对象字面量和成员访问中(obj.function ES5 中的 Ok)。

仅作记录,该标准最近由软件供应商实施,您可以在此 compatibility table 上查看哪些浏览器包含此功能(请参阅作为属性名称的保留字

【讨论】:

@Mark,不客气。请记住,JSON 只是一种 语言无关 数据交换格式,即使它的语法受到 Javascript Object Literal 语法的启发,它们之间也存在差异(不仅仅是引用的键) . @CMS,那为什么只能是双引号呢?为什么单引号在 JSON 中无效? 不允许使用单引号以使 JSON 标准尽可能简单。 JSON 只需要是 Javascript 的一个子集,它不需要尽可能多地实现 Javascript。 JSON5 superset spec 遵循 ES5 语法,因此支持不带引号的键。该库具有兼容的parsestringify 方法。 在该兼容性表链接中(在答案的底部),Reserved words 条目位于 Object/array literal extensions 部分下。并且 TL;DR,所有列出的浏览器(您听说过的所有浏览器以及大约 20 多个)都说“是”。【参考方案2】:

是的,它是无效的 JSON,否则在许多情况下会被拒绝,例如 jQuery 1.4+ 有一个检查,使未引用的 JSON 静默失败。为什么合规?

我们再举一个例子:

 myKey: "value" 
 my-Key: "value" 
 my-Key[]: "value" 

...所有这些与引号一起有效,为什么不保持一致并在所有情况下都使用它们,从而消除出现问题的可能性?

Web 开发人员世界中更常见的一个示例:在大多数浏览器中呈现的无效 html 示例数以千计……这是否可以减轻调试或维护的痛苦?完全没有,恰恰相反。

@Matthew 也是下面 cmets 中最好的一点,这个 已经 失败了,未加引号的键将在所有主要浏览器(以及任何其他实现正确),you can test it here。

【讨论】:

是的,我有一些旧的 ajax 应用程序在服务器端生成 schonky json,升级到 jquery 1.4 时由于键名周围缺少双引号而失败。 您可能需要补充一点,所有主流浏览器的JSON.parse 也会正确拒绝它。 我很好奇,在什么情况下 JQuery 1.4 会因为这种类型的无效 json 而静默失败? @Mark - 在任何情况下,它都没有正确引用或包含无效字符......基本上它会因任何无效的 JSON 而失败。 这很有趣,这不是我使用 JQuery 1.4 的经验。此外,我不认为 jquery 负责创建 json 对象,这不是浏览器的 javascript 解释器所做的吗?你指的是jquery json反序列化吗?【参考方案3】:

如果我正确理解标准,JSON 所称的“对象”实际上更接近于地图(“字典”),而不是通常意义上的实际对象。当前的标准很容易适应允许任何类型的键的扩展,使得


    "1" : 31.0,
      1 : 17,
     1n : "valueForBigInt1"

由 3 个不同元素组成的有效“对象/地图”。

如果不是因为这个原因,我相信设计者会为所有情况(可能除了关键字)在键周围加上引号。

【讨论】:

【参考方案4】:

YAML 实际上是 JSON 的超集,支持您想要做的事情。虽然它是一个超集,但它可以让您尽可能简单。

YAML 是一股清新的空气,值得您花时间来看看它。最佳起点在这里:http://en.wikipedia.org/wiki/YAML

所有语言都有库,包括 JS,例如https://github.com/nodeca/js-yaml

【讨论】:

YAML 不是 JSON 的超集。 了解原因:***.com/questions/25974485/…

以上是关于是否有任何实际理由为 JSON 键使用带引号的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 在格式化 JSON 时将我的双打转换为带引号的字符串

是否有任何在线工具可用于将无效 JSON 中的单引号替换为双引号或在 PHP 中使用无效 json 的任何解决方案?

寻找正则表达式以在大字符串中查找带引号的换行符(对于 C#)

MySQL 5.7 JSON_EXTRACT 不适用于对象中的带引号的字符串:[错误]“字符串中缺少右引号”

php 数组转换json中括号转义

关于JSON