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

cla*_*amp 179 standards json

这是有效的json吗?

{
    "a" : "x",
    "a" : "y"
}
Run Code Online (Sandbox Code Playgroud)

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

http://www.json.org/没有说明被禁止的事情.

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

use*_*322 111

简短回答:是的,但不推荐.
答案很长:这取决于你所谓的有效...


JSON数据交换格式(ECMA-404)并没有说明重复名称(键)任何东西.

但是,JavaScript Object Notation(JSON)数据交换格式(RFC7159)说:

对象中的名称应该是唯一的.

在这种情况下,必须按照RFC 2119中的规定来理解

应该这个词,或形容词"推荐",意味着在特定情况下可能存在忽略特定项目的正当理由,但在选择不同的课程之前必须理解并仔细权衡全部含义.



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

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

已经观察到JSON解析库的不同之处在于它们是否使对象成员的排序对调用软件可见.其行为不依赖于成员
排序的实现将是可互操作的,因为它们不会
受到这些差异的影响.




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

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

(换句话说,最后一次胜利).




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

org.json.JSONException: Duplicate key "status"  at
org.json.JSONObject.putOnce(JSONObject.java:1076)
Run Code Online (Sandbox Code Playgroud)

  • 对于`JSON.parse()`的[ECMA-262](http://www.ecma-international.org/ecma-262/6.0/#sec-internalizejsonproperty)规范也明确地说"在有重复的情况下name一个对象中的字符串,词法上相同键的值必须被覆盖.(换句话说,last-value-wins). (5认同)
  • @BenCrowell:据我所知,JSON不应该是有效的JavaScript,有些情况下不是,请参阅http://timelessrepo.com/json-isnt-a-javascript-subset.话虽如此,它当然受到JavaScript的启发(它甚至在JSON规范中也是如此). (3认同)
  • JSON 应该是有效的 javascript,因此检查重复键是否是文字中的有效 JS 是相关的。V8 似乎接受它们:`d8 -e 'x={"a":1,"a":2}; print(xa);'` 这将打印 2。 (2认同)
  • 值得注意的是,当使用 javascript“严格模式”时,如果有两个相同的键,chrome 将使用第二个键值对并忽略第一个。IE11 会抛出异常。 (2认同)

Tim*_*lds 107

标准(第二部分):

预计其他标准将引用此标准,严格遵守JSON文本格式,同时对各种编码细节施加限制.这些标准可能需要特定的行为.JSON本身不指定任何行为.

在标准中进一步向下(第2页),JSON对象的规范:

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

JSON对象的图表

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

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

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

  • @clamp json.org不是标准,据我所知,它不是由Emca International运营的.json.org似乎是匿名呈现的.这是**规范:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf它在json.org上的内容是无关紧要的. (7认同)
  • 我想我可以接受这个作为答案,虽然我喜欢提到@PatrickGoley,在json.org上它被称为一组键/值对,这意味着唯一性意味着它无效. (5认同)
  • @TimothyShields 并且您链接到的标准说,“JSON 语法不会对用作名称的字符串施加任何限制,不要求名称字符串是唯一的,并且不会为名称/值对的排序赋予任何意义” (5认同)
  • @clamp考虑我刚刚添加的`std :: multimap`示例.它可以序列化为具有可能重复键的JSON对象. (3认同)
  • @clamp 是一组键/值对,并不排除重复的名称。`{"a":1,"a":2}` 是一组两个不同的键/值对。事实上,甚至`{"a":1,"a":1}`也可以被认为是一组恰好只有一个元素的键/值对。事实上,它的重复可以被认为只是一个语法上的怪癖。更好的定义是“对象是从字符串(名称)到值的部分函数”。 (2认同)

too*_*ges 18

有2个文档指定JSON格式:

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

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

第二份文件说:

  1. 对象

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

所以不禁止有重复的名称,但不鼓励.


a d*_*ren 8

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

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

<object>
  <a>x</a>
  <a>y</a>
</object>
Run Code Online (Sandbox Code Playgroud)

将其转换为JSON时,您将获得以下内容:

{
  "object": {
    "a": [
      "x",
      "y"
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

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

希望有人帮助!


Max*_*oel 6

JSON规范说:

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

这里的重要部分是"无序":它意味着键的唯一性,因为您可以用来引用特定对的唯一因素是它的关键.

此外,大多数JSON库将JSON对象反序列化为哈希映射/字典,其中密钥保证唯一.使用重复键反序列化JSON对象时会发生什么情况取决于库:在大多数情况下,您将获得错误,或者只考虑每个重复键的最后一个值.

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

  • 无序意味着独特性吗?我认为set是这里的有效词 (22认同)
  • 无序的颜色集合:蓝色,绿色,绿色,蓝色,红色,蓝色,绿色 - 它有重复. (7认同)
  • 您引用的文本短语"一个对象是一组无序的名称/值对",并未出现在JSON规范中... (5认同)
  • 我现在看到你引用了json.org.它与官方"接近",但不是规范.页面顶部有一个指向规范的链接,在json.org上逐字重复.如果搜索规范,则不会出现单词"unordered",单词"set"仅出现在与JSON对象无关的上下文中. (5认同)
  • 请注意,它表示"无序设置**名称/值对**",对不是名称.也就是说,`{(a,b),(a,c)}`_is_是一个唯一的集合.所以技术上在json.org定义`{"a":1,"a":2}`是有效的但是`{"a":1,"a":2,"a":1}`不是.另请注意,[ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)(实际标准)避免使用"set"一词:`对象结构表示为一对围绕零个或多个名称/值对的大括号标记 (4认同)
  • 你指的是哪个规格?我没有在那里看到...... http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf (2认同)

小智 6

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

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

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

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

RFC-8259:

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

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

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

ECMA-404:

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

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

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

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

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


小智 5

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

[
  "div":
  {
    "p": "hello",
    "p": "universe"
  },
  "div":
  {
    "h1": "Heading 1",
    "p": "another paragraph"
  }
]
Run Code Online (Sandbox Code Playgroud)

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

<body>
 <div>
  <p>hello</p>
  <p>universe</p>
 </div>
 <div>
  <h1>Heading 1</h1>
  <p>another paragraph</p>
 </div>
</body>
Run Code Online (Sandbox Code Playgroud)

我可以看到这个问题背后的原因,但就目前情况而言......我不会相信它。