使用带引号的字符串作为JSON键是否有实际意义?

97
根据Crockford的json.org,JSON对象由成员构成,而成员由一对“键-值”(pair)组成。
每个“键-值”(pair)都由一个字符串和一个值组成,其中定义了字符串如下:
引用自

字符串是由双引号包裹的零个或多个Unicode字符序列,使用反斜杠转义。 字符被表示为单个字符字符串。 字符串与C或Java字符串非常相似。

但实际上,大多数程序员甚至不知道JSON键应该用双引号括起来,因为大多数浏览器不要求使用双引号。
在JSON中使用双引号是否有意义呢?
有效示例:
{
  "keyName" : 34
}

与无效对立的是:

{
   keyName : 34
}

22
“为什么要费心做得正确呢?”这种懒惰的想法会导致网站充斥着无效标记。为了预防一些浏览器确实需要双引号,让你的代码具备未来性。 - user229044
23
为什么要做正确的事情呢?如果没有真正的好处,那为什么要遵循其他人都不遵守的惯例呢?也许你将懒惰的思维误认为实用主义了。 - Mark Rogers
18
“没有其他人这样做”——你是从哪里得到这个想法的?每个主要平台内置的JSON序列化程序都会进行适当的引用。 - Nick Craver
7
PHP的json_encode函数生成有效的JSON,其中包括双引号字符串。也许你想到了JavaScript中的对象字面量?确实,这些可以在不用引号引用键的情况下正常工作,但那不是JSON。 - JAL
11
记录一下,多年前我发布这篇文章时,像@JAL建议的那样,我对JSON和对象字面量表示法之间的区别感到困惑。这两者具有非常相似的语法,这最终导致了在描述问题时的一些混淆。 - Mark Rogers
显示剩余4条评论
4个回答

170
JSON键应该用引号括起来的真正原因在于ECMAScript 3标识符的语义。
例如,保留字不能作为对象字面量中的属性名使用,除非加上引号。
({function: 0}) // SyntaxError
({if: 0}) // SyntaxError
({true: 0}) // SyntaxError
// etc...

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

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

Crockford本人在这个演讲中解释了,他们希望保持JSON标准的简洁性,并且不希望对其施加太多语义限制。
那是我们发现未引用名称问题的时候。原来ECMA Script 3有一个糟糕的保留字策略。保留字必须在键位置加上引号,这真是个麻烦事。当我开始将其制定为标准时,我不想把所有的保留字都放进标准里,因为那看起来很愚蠢。
当时,我试图说服人们:是的,你可以用JavaScript编写应用程序,它实际上会工作,并且是一种好的语言。但同时,我不想说:看看他们做了这么愚蠢的事情!所以我决定,我们只需引用键。
这样,我们就不必告诉任何人它有多么糟糕。
这就是为什么到今天,JSON中的键仍然被引用的原因。
ECMAScript第5版标准修复了这个问题,现在在ES5的实现中,即使是保留字也可以在对象字面量和成员访问(ES5中obj.function是可以的)中使用而无需引号。

2
@Mark,不用谢。请记住,JSON只是一种与语言无关的数据交换格式,即使它的语法受到JavaScript对象字面量语法的启发,它们之间仍然存在差异(不仅仅是引用键)。 - Christian C. Salvadó
2
@CMS,那为什么只能用双引号?为什么在JSON中单引号无效? - Pacerier
1
为了让 JSON 标准尽可能简单,禁止使用单引号。JSON 只需要是 Javascript 的一个子集,不需要实现 Javascript 的所有功能。 - thomasrutter
JSON5 superset spec 遵循 ES5 语法,因此支持未引用的键等其他功能。该库具有兼容的 parsestringify 方法。 - Inigo
在答案底部的兼容性表链接中,“保留字”条目位于“对象/数组文字扩展”部分。简而言之,所有列出的浏览器(包括你听说过的和大约20个以上的浏览器)都表示“是”。 - i336_

17

是的,这是无效的JSON,在许多情况下都会被拒绝,例如jQuery 1.4+有一个检查,使得未引用的JSON默默失败。为什么不遵守规范呢?

让我们举另一个例子:

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

所有这些情况使用引号都是有效的,为什么不保持一致并在所有情况下使用引号,消除问题的可能性呢?

在 Web 开发领域中还有一个常见例子:数千个无效的 HTML 示例可以在大多数浏览器中呈现...这是否使其更不容易调试或维护?完全不是,恰恰相反。

@Matthew 在下面的评论中也提出了最好的观点,这已经失败了,未引用的键将在所有主要的浏览器(以及任何其他正确实现它的浏览器)中使用 JSON.parse() 抛出语法错误,您可以在此处进行测试


是的,我有一些旧的ajax应用程序在服务器端生成了不良的json,由于键名周围缺少双引号,在升级到jquery 1.4时失败了。 - JAL
你可能想要补充说明的是,所有主流浏览器的 JSON.parse 也会正确地拒绝它。 - Matthew Flaschen
我很好奇,在什么情况下,JQuery 1.4会在这种无效的JSON类型下默默失败? - Mark Rogers
1
@Mark - 无论如何,它都没有被正确引用或包含无效字符...基本上任何无效的JSON都会失败。 - Nick Craver
很有趣,这不是我使用 JQuery 1.4 的经历。此外,我认为 jQuery 不负责创建 JSON 对象,难道不是浏览器的 JavaScript 解释器吗?您是指 JQuery JSON 反序列化吗? - Mark Rogers
@Mark Rogers 是的,它在反序列化时失败了。这就是我在评论中提到的 - 我有一个 PHP 页面发送 json,如 {cow:47,duck:"flapping left"},当使用 dataType 为 json、Content-Type 为 application/json 的 $.getJSON 或 $.ajax 检索时,它会失败。数据被解码为 null。然而,在 jQuery 1.3.x 中,这个无效的 json 可以正常工作。 - JAL

0

如果我理解标准正确,JSON所谓的“对象”实际上比通常意义上的对象更接近于映射(“字典”)。当前标准容易适应允许任何类型的键的扩展。

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

一个包含三个不同元素的有效的“对象/映射”。

如果不是因为这个原因,我相信设计者会让所有情况下的键周围的引号都是可选的(也许除了关键字)。


-4

YAML实际上是JSON的超集,支持您想要做的内容。尽管它是一个超集,但它可以让您保持简单。

YAML是一股清新之风,值得花时间去了解。最好的入门方式在这里:http://en.wikipedia.org/wiki/YAML

对于每种编程语言都有库,包括JS,例如https://github.com/nodeca/js-yaml


12
YAML不是JSON的超集。 - John Gibb
请参考以下有关编程的内容:有关原因的信息,请访问https://dev59.com/jV8e5IYBdhLWcg3wNINp - Ben Page

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接