JSON 语法是否允许对象中的重复键?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21832701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 20:15:24  来源:igfitidea点击:

Does JSON syntax allow duplicate keys in an object?

jsonstandards

提问by clamp

Is this valid json?

这是有效的json吗?

{
    "a" : "x",
    "a" : "y"
}

http://jsonlint.com/says yes.

http://jsonlint.com/说是的。

http://www.json.org/doesn't say anything about it being forbidden.

http://www.json.org/没有说它被禁止。

But obviously it doesn't make much sense, does it? Most implementations probably use a hashtable so it is being overriden anyways.

但显然它没有多大意义,不是吗?大多数实现可能使用哈希表,因此无论如何它都会被覆盖。

采纳答案by Timothy Shields

From the standard (p. ii):

标准 (p. ii)

It is expected that other standards will refer to this one, strictly adhering to the JSON text format, while imposing restrictions on various encoding details. Such standards may require specific behaviours. JSON itself specifies no behaviour.

预计其他标准会参考这一点,严格遵守JSON文本格式,同时对各种编码细节进行限制。此类标准可能需要特定的行为。JSON 本身不指定任何行为。

Further down in the standard (p. 2), the specification for a JSON object:

在标准 (p. 2) 的进一步下方,JSON 对象的规范:

An object structure is represented as a pair of curly bracket tokens surrounding zero or more name/value pairs. A name is a string. A single colon token follows each name, separating the name from the value. A single comma token separates a value from a following name.

Diagram for JSON Object

对象结构表示为一对围绕零个或多个名称/值对的大括号标记。名称是一个字符串。每个名称后面都有一个冒号标记,将名称与值分开。单个逗号标记将值与以下名称分开。

JSON 对象图

It does not make any mention of duplicate keys being invalid or valid, so according to the specification I would safely assume that means they are allowed.

它没有提到重复密钥无效或有效,因此根据规范,我可以安全地假设这意味着它们是允许的。

That most implementations of JSON libraries do notaccept duplicate keys does not conflict with the standard, because of the first quote.

由于第一个引号,JSON 库的大多数实现接受重复键与标准不冲突。

Here are two examples related to the C++ standard library. When deserializing some JSON object into a std::mapit would make sense to refuse duplicate keys. But when deserializing some JSON object into a std::multimapit would make sense to accept duplicate keys as normal.

以下是与 C++ 标准库相关的两个示例。当将一些 JSON 对象反序列化为 astd::map时,拒绝重复键是有意义的。但是当将一些 JSON 对象反序列化为 a 时std::multimap,像往常一样接受重复的键是有意义的。

回答by user454322

The short answer: Yes but is not recommended.
The long answer: It depends on what you call valid...

简短的回答:可以,但不推荐。
长答案:这取决于你所说的有效......


ECMA-404"The JSON Data Interchange Syntax" doesn't say anything about duplicated names (keys).


ECMA-404“JSON 数据交换语法”没有说明重复的名称(键)。


However, RFC 8259"The JavaScript Object Notation (JSON) Data Interchange Format" says:


但是,RFC 8259“JavaScript 对象表示法 (JSON) 数据交换格式”说:

The names within an object SHOULD be unique.

对象内的名称应该是唯一的。

In this context SHOULDmust be understood as specified in BCP 14:

在这种情况下应该作为规定必须理解BCP 14

SHOULDThis word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.

应该这个词,或形容词“推荐”,表示在特定情况下可能存在有效理由忽略特定项目,但在选择不同的课程之前必须理解并仔细权衡全部含义。


RFC 8259explains why unique names (keys) are good:


RFC 8259解释了为什么唯一名称(键)是好的:

An object whose names are all unique is interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. When the names within an object are not unique, the behavior of software that receives such an object is unpredictable. Many implementations report the last name/value pair only. Other implementations report an error or fail to parse the object, and some implementations report all of the name/value pairs, including duplicates.

名称都是唯一的对象是可互操作的,因为接收该对象的所有软件实现都将同意名称-值映射。当对象内的名称不唯一时,接收此类对象的软件的行为是不可预测的。许多实现仅报告姓氏/值对。其他实现会报告错误或无法解析对象,有些实现会报告所有名称/值对,包括重复项。





Also, as Serguei pointed out in the comments: ECMA-262"ECMAScript? Language Specification", reads:

此外,正如 Serguei 在评论中指出的那样:ECMA-262“ECMAScript?语言规范”,内容如下:

In the case where there are duplicate name Strings within an object, lexically preceding values for the same key shall be overwritten.

如果对象中存在重复的名称字符串,则应覆盖相同键的词法前面的值。

In other words, last-value-wins.

换句话说,最后价值获胜。



Trying to parse a string with duplicated names with the Java implementation by Douglas Crockford(the creator of JSON) results in an exception:

尝试使用Douglas Crockford(JSON 的创建者)的Java 实现解析具有重复名称的字符串会导致异常

org.json.JSONException: Duplicate key "status"  at
org.json.JSONObject.putOnce(JSONObject.java:1076)

回答by toongeorges

There are 2 documents specifying the JSON format:

有 2 个文档指定了 JSON 格式:

  1. http://json.org/
  2. https://tools.ietf.org/html/rfc7159
  1. http://json.org/
  2. https://tools.ietf.org/html/rfc7159

The accepted answer quotes from the 1st document. I think the 1st document is more clear, but the 2nd contains more detail.

接受的答案引自第一个文件。我认为第一个文件更清楚,但第二个文件包含更多细节。

The 2nd document says:

第二个文件说:

  1. Objects

    An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string. A single colon comes after each name, separating the name from the value. A single comma separates a value from a following name. The names within an object SHOULD be unique.

  1. 对象

    对象结构表示为一对大括号,围绕零个或多个名称/值对(或成员)。名称是一个字符串。每个名称后面都有一个冒号,将名称与值分开。单个逗号将值与以下名称分开。 对象内的名称应该是唯一的。

So it is not forbidden to have a duplicate name, but it is discouraged.

所以不禁止重名,但不鼓励。

回答by a darren

I came across a similar question when dealing with an API that accepts both XML and JSON, but doesn't document how it would handle what you'd expect to be duplicate keys in the JSON accepted.

在处理同时接受 XML 和 JSON 的 API 时,我遇到了一个类似的问题,但没有记录它如何处理您期望的 JSON 中的重复键。

The following is a valid XML representation of your sample JSON:

以下是示例 JSON 的有效 XML 表示形式:

<object>
  <a>x</a>
  <a>y</a>
</object>

When this is converted into JSON, you get the following:

将其转换为 JSON 后,您会得到以下信息:

{
  "object": {
    "a": [
      "x",
      "y"
    ]
  }
}

A natural mapping from a language that handles what you might call duplicate keys to another, can serve as a potential best practice reference here.

从一种处理您可能称之为重复键的语言到另一种语言的自然映射,可以作为潜在的最佳实践参考。

Hope that helps someone!

希望对某人有所帮助!

回答by Max Noel

The JSON spec says this:

JSON 规范是这样说的:

An object is an unordered set of name/value pairs.

对象是一组无序的名称/值对。

The important part here is "unordered": it implies uniqueness of keys, because the only thing you can use to refer to a specific pair is its key.

这里的重要部分是“无序”:它意味着键的唯一性,因为唯一可以用来指代特定对的是它的键。

In addition, most JSON libs will deserialize JSON objects to hash maps/dictionaries, where keys are guaranteed unique. What happens when you deserialize a JSON object with duplicate keys depends on the library: in most cases, you'll either get an error, or only the last value for each duplicate key will be taken into account.

此外,大多数 JSON 库会将 JSON 对象反序列化为哈希映射/字典,其中键保证唯一。当您反序列化具有重复键的 JSON 对象时会发生什么取决于库:在大多数情况下,您要么会收到错误,要么只会考虑每个重复键的最后一个值。

For example, in Python, json.loads('{"a": 1, "a": 2}')returns {"a": 2}.

例如,在 Python 中,json.loads('{"a": 1, "a": 2}')返回{"a": 2}.

回答by Colin Saxton

SHOULD be unique does not mean MUST be unique. However, as stated, some parsers would fail and others would just use the last value parsed. However, if the spec was cleaned up a little to allow for duplicates then I could see a use where you may have an event handler which is transforming the JSON to HTML or some other format...in such cases it would be perfectly valid to parse the JSON and create another document format...

应该是唯一的并不意味着必须是唯一的。但是,如前所述,一些解析器会失败,而其他解析器只会使用最后解析的值。但是,如果规范稍微清理一下以允许重复,那么我可以看到一个用途,您可能有一个将 JSON 转换为 HTML 或其他格式的事件处理程序......在这种情况下,它是完全有效的解析 JSON 并创建另一种文档格式...

[
  "div":
  {
    "p":"hello",
    "p":"universe"
  }
  "div":
  {
    "h1":"Heading 1",
    "p":"another paragraph"
  }
]

could then easily parse to html for example

然后可以轻松解析为 html 例如

<body>
 <div>
  <p>hello</p>
  <p>universe</p>
 </div>
 <div>
  <h1>Heading 1</h1>
  <p>another paragraph</p>
 </div>
</body>

I can see the reasoning behind the question but as it stands...I wouldn't trust it.

我可以看到问题背后的推理,但就目前而言......我不相信它。

回答by xthr33

Posting and answer because there is a lot of outdated ideas and confusion about the standards. As of December 2017, there are two competing standards:

发布和回答,因为有很多关于标准的过时的想法和混乱。截至 2017 年 12 月,有两个相互竞争的标准:

RFC 8259 - https://tools.ietf.org/html/rfc8259

RFC 8259 - https://tools.ietf.org/html/rfc8259

ECMA-404 - http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf

ECMA-404 - http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf

json.org suggests ECMA-404 is thestandard, but this site does not appear to be an authority. While I think it's fair to consider ECMA the authority, what's important here is, the only difference between the standards (regarding unique keys) is that RFC 8259 says the keys shouldbe unique, and the ECMA-404 says they are not requiredto be unique.

json.org表明ECMA-404标准,但这个网站似乎并没有成为一个权威。虽然我认为这是公平考虑ECMA权威,什么是这里重要的是,该标准(关于唯一键)之间的唯一区别是,RFC 8259说的按键应该是唯一的,而ECMA-404说,他们并不需要为独特的。

RFC-8259:

RFC-8259:

"The names within an object SHOULD be unique."

“对象内的名称应该是唯一的。”

The word "should" in all caps like that, has a meaning within the RFC world, that is specifically defined in another standard (BCP 14, RFC 2119 - https://tools.ietf.org/html/rfc2119) as,

像这样的所有大写字母中的“应该”一词在 RFC 世界中具有含义,在另一个标准(BCP 14、RFC 2119 - https://tools.ietf.org/html/rfc2119)中明确定义为,

  1. SHOULD This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.
  1. 应该这个词,或形容词“推荐”,表示在特定情况下可能存在有效理由忽略特定项目,但在选择不同的课程之前必须理解并仔细权衡全部含义。

ECMA-404:

ECMA-404:

"The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs."

“JSON 语法不对用作名称的字符串施加任何限制,不要求名称字符串是唯一的,并且不对名称/值对的排序赋予任何意义。”

So, no matter how you slice it, it's syntactically valid JSON.

所以,无论你如何切片,它在语法上都是有效的 JSON

The reason given for the unique key recommendation in RFC 8259 is,

RFC 8259 中给出的唯一密钥建议的原因是,

An object whose names are all unique is interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. When the names within an object are not unique, the behavior of software that receives such an object is unpredictable. Many implementations report the last name/value pair only. Other implementations report an error or fail to parse the object, and some implementations report all of the name/value pairs, including duplicates.

名称都是唯一的对象是可互操作的,因为接收该对象的所有软件实现都将同意名称-值映射。当对象内的名称不唯一时,接收此类对象的软件的行为是不可预测的。许多实现仅报告姓氏/值对。其他实现会报告错误或无法解析对象,有些实现会报告所有名称/值对,包括重复项。

In other words, from the RFC 8259 viewpoint, it's valid but your parser may barf and there's no promise as to which, if any, value will be paired with that key. From the ECMA-404 viewpoint (which I'd personally take as the authority), it's valid, period. To me this means that any parser that refuses to parse it is broken. It should at least parse according to both of these standards. But how it gets turned into your native object of choice is, in any case, unique keys or not, completely dependent on the environment and the situation, and none of that is in the standard to begin with.

换句话说,从 RFC 8259 的角度来看,它是有效的,但您的解析器可能会失败,并且无法保证哪个值(如果有)与该键配对。从 ECMA-404 的观点(我个人认为是权威)来看,它是有效的。对我来说,这意味着任何拒绝解析它的解析器都会被破坏。它至少应该根据这两个标准进行解析。但是,它如何变成您选择的本机对象,在任何情况下,键是否唯一,完全取决于环境和情况,而这些都不是开始时的标准。

回答by aknoepfel

Asking for purpose, there are different answers:

问目的,有不同的答案:

Using JSON to serialize objects (JavaScriptObjectNotation), each dictionary element maps to an indivual object property, so different entries defining a value for the same property has no meaning.

使用 JSON 序列化对象 (JavaScriptObjectNotation),每个字典元素映射到一个单独的对象属性,因此为同一属性定义值的不同条目没有意义。

However, I came over the same question from a very specific use case: Writing JSON samples for API testing, I was wondering how to add comments into our JSON file without breaking the usability. The JSON spec does not know comments, so I came up with a very simple approach:

但是,我从一个非常具体的用例中遇到了同样的问题:为 API 测试编写 JSON 示例,我想知道如何在不破坏可用性的情况下将注释添加到我们的 JSON 文件中。JSON 规范不知道注释,所以我想出了一个非常简单的方法:

To use duplicate keys to comment our JSON samples. Example:

使用重复键来评论我们的 JSON 示例。例子:

{ "property1" : "value1", "REMARK" : "... prop1 controls ...", "property2" : "value2", "REMARK" : "... value2 raises an exception ...", }

{ "property1" : "value1", "REMARK" : "... prop1 controls ...", "property2" : "value2", "REMARK" : "... value2 raises an exception ...", }

The JSON serializers which we are using have no problems with these "REMARK" duplicates and our application code simply ignores this little overhead.

我们使用的 JSON 序列化器对这些“REMARK”重复没有问题,我们的应用程序代码只是忽略了这个小开销。

So, even though there is no meaning on the application layer, these duplicates for us provide a valuable workaround to add comments to our testing samples without breaking the usability of the JSON.

因此,即使在应用程序层上没有意义,这些重复为我们提供了一种有价值的解决方法,可以在不破坏 JSON 可用性的情况下向我们的测试样本添加注释。

回答by John Carlson

The standard does say this:

标准确实是这样说的:

Programming languages vary widely on whether they support objects, and if so, what characteristics and constraints the objects offer. The models of object systems can be wildly divergent and are continuing to evolve. JSON instead provides a simple notation for expressing collections of name/value pairs. Most programming languages will have some feature for representing such collections, which can go by names like record, struct, dict, map, hash, or object.

编程语言在是否支持对象方面存在很大差异,如果支持,对象提供哪些特征和约束。对象系统的模型可能千差万别,并且还在不断发展。相反,JSON 提供了一种简单的表示法来表示名称/值对的集合。大多数编程语言都有一些用于表示此类集合的功能,这些功能可以使用记录、结构、字典、映射、哈希或对象等名称。

The bug is in node.js at least. This code succeeds in node.js.

该错误至少在 node.js 中。此代码在 node.js 中成功。

try {
     var json = {"name":"n","name":"v"};
     console.log(json); // outputs { name: 'v' }
} catch (e) {
     console.log(e);
}

回答by svidgen

It's not defined in the ECMA JSON standard. And generally speaking, a lack of definition in a standard means, "Don't count on this working the same way everywhere."

它没有在ECMA JSON 标准中定义。一般来说,标准中缺乏定义意味着,“不要指望这在任何地方都以同样的方式工作。”

If you're a gambler, "many" JSON engines will allow duplication and simply use the last-specified value. This:

如果您是赌徒,“许多”JSON 引擎将允许重复并仅使用最后指定的值。这个:

var o = {"a": 1, "b": 2, "a": 3}

Becomes this:

变成这样:

Object {a: 3, b: 2}

But if you're not a gambler, don't count on it!

但是,如果您不是赌徒,请不要指望它!