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


91

JSON规范说JSON是对象或数组。如果是物体,

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

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

为什么?

从而,

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

并不是

{Property1:"Value1",Property2:18}

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


问题2:使用Javascript进行评估时,上述两种表示形式在语义上有区别吗?


1
@Bruno:您可以用相同的方式来谈论XML……可悲的是,有些人可能正在尝试将XML用作编程语言……
Mike DeSimone 2010年

2
+1 ...似乎确实是一个特殊的矛盾....“带引号”使它成为标准的JSON,但无法使用eval()(即javascript)。
skaffman 2010年

2
@bruno,不。如果将其展开,它将变为“采用Javascript对象表示法”,这很好
Dave Archer 2010年

2
@skaffman —当在JavaScript中被跳过时将起作用。
昆汀2010年

1
@Bruno-JSON是一种数据格式。“在JSON中”是指-根据规范格式化的数据。
Cheeso 2010年

Answers:


57

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

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

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

问题2:使用Javascript进行评估时,上述两种表示形式在语义上有区别吗?

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


3
不,这是不正确的。CMS的答案正确。这个答案只是真实原因的一个很好的副作用。除了更容易解释之外,编写解析器也更加简单,因为您可以将解析规则重新用于标识符上的字符串。
布列塔尼

除此之外,还有一点语义上的差异,即如果标识符恰好是保留字,那么它将被解释为该字而不是标识符。
列塔尼

2
对CMS的答案+1,是正确的。双引号不是代码约定,但是您要避免将保留字作为对象中的键。例如:{property1:“ abc”,this:“ def”}是错误的(这是一个保留关键字)
Sorin Mocanu 2010年

问题2:使用JSON.parse函数时Javascript的微小区别:JSON.parse('{"a":1}') 效果很好,为什么JSON.parse('{a:1}')引发异常
nhnghia

@nhnghia —问题2是关于将源代码评估为JavaScript而不是JSON。JSON.parse是用JavaScript实现的JSON解析器,不是JavaScript解析器。
昆汀

134

我从道格拉斯·克罗克福德(Douglas Crockford,JSON标准的创建者)给雅虎的演讲中引用了一段话。

他谈到了他如何发现 JSON的,以及他为什么决定使用带引号的密钥的其他信息

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

当时,我试图说服人们:是的,您可以使用JavaScript编写应用程序,它实际上可以正常工作,并且是一种很好的语言。那么,我不想同时说:看看他们所做的这件事真是愚蠢!因此,我决定让我们只引用这些键。
那样,我们不必告诉任何人它是多么的糟糕。

这就是为什么到目前为止,键都用JSON引用。

您可以在此处找到完整的视频和成绩单。


嗯... JSON标准的创建者?我认为这是一个夸大的说法。JSON是JavaScript对象符号,来自Javascript(ECMA)规范。
索林·莫卡努

42
@Sorin:不要将JSON与JavaScript Object文字混淆。JSON是一种与语言无关的数据交换格式,由Crockford在2006年提出(tools.ietf.org/html/rfc4627),其语法与JavaScript Object文字不同(bclary.com/2004/11/07/#a-11.1 .5),基本上只允许使用字符串键,并且值必须对象数组数字字符串或以下文字名称之一:falsenull true。JavaScript中的对象文字可以具有如IdentifiersString文字数字文字,并且值可以是任何类型的表达式 ...
CMS 2010年

@CMS今天的JavaScript允许在对象构造函数表达式中使用速记标识符,例如:{ a },其中属性“ a”复制全局或局部变量“ a”的值。
Hydroper

@CMS还有计算键:{[key]: value}
Hydroper

0

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


0

在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中作为标记/标识符评估的字符,因此最好将所有标识符放在字符串中以保持一致性。


-2

我认为,对Cheeso问题的正确答案是实施超过了文档。它不再需要字符串作为键,而是其他东西,它可以是字符串(即用引号引起来),也可以是(可以)任何可用作变量名的东西,我猜这意味着以字母_开头或$,并且仅包含字母,数字以及$和_。

我想为下一个以与我相同的想法访问此问题的人简化其余部分。这是肉:

变量名称用作对象键时,不会在JSON中内插(感谢Friedo!)

Breton使用“ identifier”而不是“ key”写道:“如果标识符碰巧是保留字,则将其解释为该字而不是标识符。” 这可能是正确的,但是我尝试了一下却没有任何麻烦:

var a = {do:1,long:2,super:3,abstract:4,var:5,break:6,boolean:7};
a.break

=> 6

关于使用引号,Quentin写道:“ ...但您不必这样做,除非[key]包含某些字符(或使它们成为关键字的字符组合)”

我发现前一部分(某些字符)是正确的,使用@符号(实际上,我认为$和_是不会导致错误的唯一字符):

var a = {a@b:1};

=>语法错误

var a = {"a@b":1};
a['a@b']

=> 1

但是如上所示,括号内的关键词是不正确的。

我想要的东西是有效的,因为开头{和冒号之间,或逗号和冒号之间的后续属性之间的文本用作未加引号的字符串来构成对象键,或者如Friedo所说,那里的变量名没有t插值:

var uid = getUID();
var token = getToken();            // Returns ABC123
var data = {uid:uid,token:token};
data.token

=> ABC123


-3

如果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

因此,即使您的示例确实产生了相同的结果,它们在“原始代码”中的等效结果也不会相同。也许那是为什么?不知道,只是个主意。


3
@David,变量名称用作对象键时不会在JS中内插。{ bar: 'goodbye' }不会将键名称设置为的值bar,而是将其设置为bar。其他人对规范要求加引号的原因是正确的:这是为了避免关键字和特殊字符冲突。
Friedo 2010年

-3

如果仅在必要时使用名称引号,则可能会减少数据大小

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.