在 JSON 中,为什么每个名称都被引用?

IT技术 javascript json
2021-01-21 01:07:22

JSON 规范说 JSON 是一个对象或一个数组。在对象的情况下,

对象结构被表示为一对大括号围绕零个或多个名称/值对(或成员)。 名称是一个字符串。 ...

后来,规范说字符串用引号括起来。

为什么?

因此,

{"Property1":"Value1","Property2":18}

并不是

{Property1:"Value1",Property2:18}

问题 1:为什么不允许名称/值对中的名称是不带引号的标识符?


问题 2:在 Javascript 中评估时,上述两种表示之间是否存在语义差异?

6个回答

我引用了 Douglas Crockford(JSON 标准的创建者)给雅虎的演讲。

他谈到了他如何发现JSON 的,以及为什么他决定使用带引号的键

.... 那是我们发现未引用名称问题的时候。事实证明,ECMA Script 3 有一个重击保留字策略。保留字必须在关键位置引用,实在是太麻烦了。当我开始将其制定为标准时,我不想将所有保留字都放在标准中,因为这看起来很愚蠢。

当时,我试图说服人们:是的,你可以用 JavaScript 编写应用程序,它实际上可以工作,而且它是一种很好的语言。然后,我不想同时说:看看他们所做的这件非常愚蠢的事情!所以我决定,相反,让我们只引用键。
这样,我们就不必告诉任何人它有多糟糕。

这就是为什么直到今天,键都在 JSON 中引用。

您可以在此处找到完整的视频和文字记录

嗯…… JSON 标准创造者?!我认为这是夸大其词。JSON 是 JavaScript 对象表示法,来自 Javascript (ECMA) 规范。
2021-03-15 01:07:22
@Sorin:不要将 JSON 与 JavaScript 对象文字混淆。JSON 是一种与语言无关的数据交换格式,由 Crockford 于 2006 年提出(tools.ietf.org/html/rfc4627),其语法不同于 JavaScript 对象字面量(bclary.com/2004/11/07/#a-11.1 .5 ),基本上只允许字符串键和值必须objectarraynumberstring或以下文字名称之一:falsenull trueJavaScript 中的对象字面量可以将键作为标识符字符串字面量数字文字,值可以是任何类型的表达式...
2021-03-15 01:07:22
@CMS 今天的 JavaScript 允许在对象构造函数表达式中使用速记标识符,例如:{ a },其中属性 'a' 复制全局或局部变量 'a' 的值。
2021-03-31 01:07:22
@CMS 还有计算键: {[key]: value}
2021-04-09 01:07:22

问题 1:为什么不允许名称/值对中的名称是不带引号的标识符?

JSON 的设计理念是“保持简单”

“有报价的名字"是一个简单了很多比“你可能引述其名称"',但你不必,除非它们包含某些字符(或字符,将使其成为一个关键词的组合),并'"可能需要根据被引用在您选择的分隔符上”

问题 2:在 Javascript 中评估时,上述两种表示之间是否存在语义差异?

不。在 JavaScript 中,它们是相同的。

不,这是不正确的。CMS 有正确的答案。这个答案只是真正原因的一个很好的副作用。除了更容易解释之外,编写解析器也更简单,因为您可以对标识符上的字符串重用解析规则。
2021-03-17 01:07:22
@nhnghia — 问题 2 是关于将源代码评估为 JavaScript而不是 JSON。JSON.parse是用 JavaScript 实现的 JSON 解析器,它不是 JavaScript 解析器。
2021-03-23 01:07:22
问题2:Javascript使用JSON.parsefunction时的一个小差异JSON.parse('{"a":1}') 效果很好,为什么JSON.parse('{a:1}')引发异常
2021-03-26 01:07:22
除此之外,如果一个标识符恰好是一个保留字,它会被解释为那个词而不是一个标识符。
2021-03-29 01:07:22
+1 对 CMS 的回答,这是正确的。双引号不是代码约定,但您希望避免将保留字用作对象中的键。例如:{ property1: "abc", this: "def" } 是错误的(这是一个保留关键字)
2021-04-02 01:07:22

这两个:和空白被允许在标识符。如果没有引号,则在尝试确定标识符的确切构成时会导致歧义。

在 javascript 中,对象可以像带有密钥对的散列/散列表一样使用。

但是,如果您的密钥具有 javascript 无法标记为名称的字符,则在尝试像对象上的属性而不是密钥一样访问它时,它会失败。

var test  = {};
test["key"] = 1;
test["#my-div"] = "<div> stuff </div>";

// test = { "key": 1, "#my-div": "<div> stuff </div>" };

console.log(test.key);           // should be 1
console.log(test["key"]);        // should be 1
console.log(test["#my-div"]);    // should be "<div> stuff </div>";
console.log(test.#my-div);       // would not work.

标识符有时可能包含无法在 javascript 中被评估为标记/标识符的字符,因此最好将所有标识符放在字符串中以保持一致性。

如果 json 描述对象,那么在实践中你会得到以下内容

var foo = {};

var bar = 1;

foo["bar"] = "hello";
foo[bar] = "goodbye";

那么,

foo.bar == "hello";
foo[1] == "goodbye" // in setting it used the value of var bar

因此,即使您的示例确实产生了相同的结果,它们在“原始代码”中的等价物也不会。也许这就是为什么?不知道,只是一个想法。

@David,当用作对象键时,不会在 JS 中插入变量名。{ bar: 'goodbye' }不会将键名设置为 的值bar,它只是bar. 其他人对规范需要引号的原因是正确的:这是为了避免关键字和特殊字符冲突。
2021-03-31 01:07:22