这是有效的json吗?

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

http://jsonlint.com/的答案是肯定的。

http://www.json.org/没有说任何关于它是禁止的。

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


当前回答

According to RFC-7159, the current standard for JSON published by the Internet Engineering Task Force (IETF), states "The names within an object SHOULD be unique". However, according to RFC-2119 which defines the terminology used in IETF documents, the word "should" in fact means "... 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." What this essentially means is that while having unique keys is recommended, it is not a must. We can have duplicate keys in a JSON object, and it would still be valid.

从实际应用中,我已经看到,当在JSON中发现重复的键时,会考虑来自最后一个键的值。

其他回答

在c#中,如果你反序列化为Dictionary<string, string>,它接受最后一个键值对:

string json = @"{""a"": ""x"", ""a"": ""y""}";
var d = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
// { "a" : "y" }

如果你试图反序列化到

class Foo
{
    [JsonProperty("a")]
    public string Bar { get; set; }

    [JsonProperty("a")]
    public string Baz { get; set; }
}

var f = JsonConvert.DeserializeObject<Foo>(json);

你会得到一个Newtonsoft.Json.JsonSerializationException异常。

从标准(p. ii):

预计其他标准将引用此标准,严格遵循JSON文本格式,而 对各种编码细节施加限制。这种标准可能需要具体的行为。JSON 本身不指定任何行为。

在标准(第2页)中,JSON对象的规范如下:

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

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

大多数JSON库的实现不接受重复的键,这与标准并不冲突,因为第一个引用。

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

According to RFC-7159, the current standard for JSON published by the Internet Engineering Task Force (IETF), states "The names within an object SHOULD be unique". However, according to RFC-2119 which defines the terminology used in IETF documents, the word "should" in fact means "... 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." What this essentially means is that while having unique keys is recommended, it is not a must. We can have duplicate keys in a JSON object, and it would still be valid.

从实际应用中,我已经看到,当在JSON中发现重复的键时,会考虑来自最后一个键的值。

有两个文档指定JSON格式:

http://json.org/ https://www.rfc-editor.org/rfc/rfc7159

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

第二份文件说:

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

所以不禁止使用重复的名字,但不鼓励使用。

简短的回答是:可以,但不建议使用。 长话短说:这取决于你如何定义有效……

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

然而,RFC 8259“JavaScript对象符号(JSON)数据交换格式”规定:

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

在这种情况下,必须按照BCP 14的规定理解SHOULD:

这个词,或者形容词“RECOMMENDED”,是指那里吗 在特定情况下可能存在有效的理由忽略 特定的项目,但必须充分理解的含义和 在选择不同的路线之前仔细权衡。

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

在某种意义上,名称都是唯一的对象是可互操作的 所有接收该对象的软件实现都会同意 名称-值映射。当对象中的名称不是时 唯一的,软件接收这样一个对象的行为是 不可预测的。许多实现报告姓氏/值对 只有。属性的其他实现报告错误或未能解析 对象,一些实现报告所有的名称/值对, 包括重复。


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

如果一个对象中有重复的name string,则应覆盖相同键的词法前面的值。

换句话说,最后的价值才是赢家。


试图用Douglas Crockford (JSON的创造者)的Java实现解析具有重复名称的字符串会导致一个异常:

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