这是有效的JSON吗?
{
"a" : "x",
"a" : "y"
}
http://jsonlint.com/ 表示是可以的。
http://www.json.org/ 并没有说明它是被禁止的。
但显然这并没有多大意义,对吧? 大多数实现可能使用哈希表,因此它总是被覆盖。
这是有效的JSON吗?
{
"a" : "x",
"a" : "y"
}
http://jsonlint.com/ 表示是可以的。
http://www.json.org/ 并没有说明它是被禁止的。
但显然这并没有多大意义,对吧? 大多数实现可能使用哈希表,因此它总是被覆盖。
对象内的名称应该是唯一的。
在这种情况下,SHOULD 必须按照 BCP 14 中指定的方式理解:SHOULD 这个词或形容词“推荐”表示,在特定情况下可能存在忽略特定项的有效原因,但必须充分理解并仔细权衡选择不同路线的全部影响。
RFC 8259解释了为什么独特的名称(键)很好:
所有名称都是独特的对象在互操作性方面是可互换的,因为接收该对象的所有软件实现将就名称-值映射达成一致。当对象内的名称不唯一时,接收此类对象的软件行为是不可预测的。许多实现仅报告最后一个名称/值对。其他实现报告错误或无法解析对象,而某些实现报告所有名称/值对,包括重复项。
换句话说,以最后一个值为准。如果对象内存在重复名称的字符串,则同一键的词汇上一个值将被覆盖。
org.json.JSONException: Duplicate key "status" at
org.json.JSONObject.putOnce(JSONObject.java:1076)
根据标准 (p. ii):
预计其他标准将参考此JSON文本格式的标准,严格遵守JSON文本格式,同时对各种编码细节施加限制。这些标准可能需要特定的行为。JSON本身不指定任何行为。
在标准的后面部分(p.2),提供了JSON对象的规范:
对象结构表示为一对括号标记,包围零个或多个名称/值对。名称是一个字符串。每个名称后面跟随一个冒号标记,将名称与值分开。单个逗号标记将一个值与下一个名称分隔开。
该规范没有提到重复键是无效还是有效的,因此根据规范,我可以安全地假设它们被允许。
大多数JSON库的实现并不接受重复的键,并不与该标准冲突,因为第一条引用说明了这一点。
以下是两个与C++标准库相关的示例。当将某些JSON对象反序列化为std::map
时,拒绝重复键是有意义的。但是,当将某些JSON对象反序列化为std::multimap
时,接受重复键就像正常一样。
std::multimap
示例。它可以被序列化为一个JSON对象,其中可能存在重复的键。 - Timothy Shields{"a":1,"a":2}
是两个不同键值对的集合。事实上,即使 {"a":1,"a":1}
可以被看作是一组只有一个元素的键值对集合。它被重复使用只是一种语法上的怪异。更好的定义应该是:“对象是从字符串(名称)到值的部分函数”。 - Marcelo Cantos有两个文件指定了JSON格式:
采纳的答案引用了第一个文件。我认为第一个文件更加清晰,但第二个文件包含更多细节。
第二个文件说:
- 对象
对象结构表示为一对花括号,括在零个或多个名称/值对(或成员)周围。名称是一个字符串。每个名称后面跟随一个冒号,将名称与值分开。单个逗号将值与后面的名称分隔开。 对象中的名称应该是唯一的。
因此,重复名称不是被禁止的,但也并不鼓励这样做。
在处理一个既能接受XML又能接受JSON的API时,我遇到了一个类似的问题,但是它没有说明如何处理你预期在JSON中出现的重复键。
以下是您的示例JSON的有效XML表示:
<object>
<a>x</a>
<a>y</a>
</object>
当它被转换成JSON格式时,你会得到以下内容:
{
"object": {
"a": [
"x",
"y"
]
}
}
一种处理所谓的重复键的语言到另一种语言的自然映射,可以作为潜在的最佳实践参考。希望这能帮助某些人!
"对象中的名称应该是唯一的。"
“SHOULD”这样大写的单词在RFC世界中是有特定含义的,这个含义在另一个标准(BCP 14, RFC 2119 - https://www.rfc-editor.org/rfc/rfc2119)中有明确定义,意思是:
- SHOULD 这个词或者形容词“RECOMMENDED”,意思是在特定情况下可能存在忽略某个特定项的正当理由,但在选择其他方案之前必须充分理解并仔细权衡其全部影响。
ECMA-404:
“JSON语法对用作名称的字符串没有任何限制,不要求名称字符串唯一,并且不赋予名称/值对排序任何意义。”
所以,无论你怎么看待它,它在语法上都是有效的JSON。
RFC 8259推荐使用唯一键的原因是:
一个对象的名称都是唯一的,这意味着所有接收该对象的软件实现都将同意名称-值映射。当对象中的名称不唯一时,接收此类对象的软件的行为是不可预测的。许多实现仅报告最后一个名称/值对。其他实现会报告错误或无法解析对象,而某些实现会报告所有名称/值对,包括重复项。{ (a,b), (a,c) }
是一个独特的集合。因此,在 json.org 的定义下,{"a":1,"a":2}
是有效的,但 {"a":1,"a":2,"a":1}
则无效。此外,请注意ECMA-404(实际标准)避免使用“set”一词:一个对象结构被表示为一对花括号标记,括号中包含零个或多个名称/值对。
- Serguei“应该是唯一的”并不意味着“必须是唯一的”。然而,正如所述,某些解析器可能会失败,而其他解析器只会使用最后一个解析的值。但是,如果规范稍微进行了清理以允许重复,则我可以看到一种用途,即您可能有一个事件处理程序,它将JSON转换为HTML或其他格式...在这种情况下,解析JSON并创建另一个文档格式将是完全有效的...”
[
"div":
{
"p": "hello",
"p": "universe"
},
"div":
{
"h1": "Heading 1",
"p": "another paragraph"
}
]
然后可以轻松解析为HTML,例如:
<body>
<div>
<p>hello</p>
<p>universe</p>
</div>
<div>
<h1>Heading 1</h1>
<p>another paragraph</p>
</div>
</body>
{"div":{"p":"hello","p":"universe"}, "div":{"h1":"Heading 1","p":"another paragraph"}}
。现在,许多人和框架将JSON对象视为无序字典,但JavaScript和例如MongoDB的API依赖于字典中键的顺序,因此您建议的(有序字典)并不罕见。您只需要一个专门的解析器。 - binki这在ECMA JSON标准中没有定义。一般来说,在标准中缺乏定义意味着“不要指望它在所有地方都能以相同的方式工作”。
如果你想冒险,"许多"JSON引擎将允许重复,并简单地使用最后指定的值。例如:
var o = {"a": 1, "b": 2, "a": 3}
变成这个:
Object {a: 3, b: 2}
但如果你不是一个赌徒,就别指望了!
Dictionary<string, string>
,会移除第一个键值对。 - Sam Leach