Does JSON syntax allow duplicate keys in an object?
Does JSON syntax allow duplicate keys in an object?
Is this valid json?
"a" : "x",
"a" : "y"
http://jsonlint.com/ says yes.
http://www.json.org/ doesn't say anything about it being forbidden.
But obviously it doesn't make much sense, does it?
Most implementations probably use a hashtable so it is being overriden anyways.
Dictionary<string, string>
In case anyone arrives here hoping for a solution to find duplicate values in JSON strings, check out the free online json validator
– Pepijn Olivier
May 11 '15 at 10:37
jsonlint.com says yes. it does not, it removes all but the last key-value pair and then validates it, which makes it valid
– Tim Castelijns
Sep 9 '15 at 12:58
Yes, it's valid semantically according to the stanard. But as you say, this will likely break so many places, no-one should use it this way.
– Herbert Van-Vliet
Nov 21 '15 at 9:27
Then the standard is broken
– Brad Thomas
Dec 18 '15 at 22:22
11 Answers
11
From the standard (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.
Further down in the standard (p. 2), the specification for a JSON object:
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.
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 not accept duplicate keys does not conflict with the standard, because of the first quote.
Here are two examples related to the C++ standard library. When deserializing some JSON object into a std::map
it would make sense to refuse duplicate keys. But when deserializing some JSON object into a std::multimap
it would make sense to accept duplicate keys as normal.
std::map
std::multimap
i guess i can accept this as an answer, though i like the mention of @PatrickGoley that on json.org it is called a set of key/value-pairs which implies uniqueness which would mean it is not valid.
– clamp
Feb 17 '14 at 16:02
@clamp json.org is not the standard and, as far I can tell, is not run by Emca International. json.org seems presented anonymously. This is the specification: ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf What it says on json.org is not relevant.
– Timothy Shields
Feb 17 '14 at 16:05
@clamp Consider the
std::multimap
example I just added. It can be serialized as a JSON object with potentially duplicate keys.– Timothy Shields
Feb 17 '14 at 16:16
std::multimap
The short answer: Yes but is not recommended.
The long answer: It depends on what you call valid...
The JSON Data Interchange Format (ECMA-404) doesn't say anything about duplicated names (keys).
However, The JavaScript Object Notation (JSON) Data Interchange Format) (RFC7159) says:
The names within an object SHOULD be unique.
In this context should must be understood as specified in RFC 2119
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.
RFC 7159 explains why unique names (keys) are good:
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.
JSON parsing libraries have been observed to differ as to whether
or not they make the ordering of object members visible to calling
software. Implementations whose behavior does not depend on member
ordering will be interoperable in the sense that they will not be
affected by these differences.
Also, as Serguei pointed out in the comments: ECMA-262 "ECMAScript® Language Specification", reads:
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:
org.json.JSONException: Duplicate key "status" at
org.json.JSONObject.putOnce(JSONObject.java:1076)
JSON is supposed to be valid javascript, so it's relevant to check whether duplicate keys are valid JS in literals. V8 seems to accept them:
d8 -e 'x="a":1,"a":2; print(x.a);'
This prints 2.– Ben Crowell
Jun 10 '16 at 21:27
d8 -e 'x="a":1,"a":2; print(x.a);'
Also the ECMA-262 spec for
JSON.parse()
explicitly says 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).– Serguei
Jun 17 '16 at 17:38
JSON.parse()
In the case where there are duplicate name Strings within an object, lexically preceding values for the same key shall be overwritten.
@BenCrowell: As far as I know, JSON is not supposed to be valid JavaScript and there are cases where it's not, see timelessrepo.com/json-isnt-a-javascript-subset. With that said, it was of course heavily inspired by JavaScript (it even says so in the JSON specification).
– Simon Touchtech
Aug 17 '16 at 13:03
SHOULD is not MUST, so shouldn’t the short answer be “yes”?
– binki
Jul 6 '17 at 16:29
@binki Yes, it should. And "it depends on what you call valid" is nonsense - what's valid is what conforms to the requirements and allowances of the specification, the rest is recommendation. What this answer got right are the parts copied and pasted from the specifications, sadly the conclusions it draws based on them are wrong.
– Paul Crovella
Jul 26 '17 at 2:01
There are 2 documents specifying the JSON format:
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:
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.
So it is not forbidden to have a duplicate name, but it is discouraged.
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.
The following is a valid XML representation of your sample JSON:
<object>
<a>x</a>
<a>y</a>
</object>
When this is converted into JSON, you get the following:
"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!
The JSON spec says this:
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.
For example, in Python, json.loads('"a": 1, "a": 2')
returns "a": 2
.
json.loads('"a": 1, "a": 2')
"a": 2
does unordered imply uniqueness? I think set is the operative word here
– Patrick Goley
Feb 17 '14 at 15:33
An unordered collection of colors: Blue, Green, Green, Blue, Red, Blue, Green - It has duplicates.
– Timothy Shields
Feb 17 '14 at 15:33
The text phrase you are quoting, "An object is an unordered set of name/value pairs," does not appear in the JSON spec...
– Timothy Shields
Feb 17 '14 at 15:36
I see now that you were quoting json.org. It's 'close' to official, but it's not the specification. Top of the page has a link to the specification, which is repeated verbatim on json.org. If you search the spec., the word "unordered" does not appear, and the word "set" appears only in contexts unrelated to JSON objects.
– Timothy Shields
Feb 17 '14 at 15:38
Note that it says "unordered set of name/value pairs", pairs not names. That is,
(a,b), (a,c)
is a unique set. So technically under the json.org definition "a":1,"a":2
is valid but "a":1,"a":2,"a":1
is not. Also note that ECMA-404 (the actual standard) avoids using the word "set": An object structure is represented as a pair of curly bracket tokens surrounding zero or more name/value pairs.
– Serguei
Jun 17 '16 at 18:04
(a,b), (a,c)
"a":1,"a":2
"a":1,"a":2,"a":1
An object structure is represented as a pair of curly bracket tokens surrounding zero or more name/value pairs.
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.
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:
To use duplicate keys to comment our JSON samples.
Example:
"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.
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.
This is a bad idea. By including duplicate keys, even if you don't need to read the data in them, you're relying on undefined behaviour. Some parsers, such as Crockford's JSON-java parser, throw an exception and refuse to parse the data.
– Richard Smith
Mar 28 '16 at 14:13
Actually working perfectly in our environment, so serving my needs, even though I agree with you that it's some kind out of spec ;)
– aknoepfel
Jul 22 '16 at 16:14
@RichardSmith I’d say the parsers and newer ES specs have defined the behavior.
– binki
Jul 6 '17 at 16:36
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...
[
"div":
"p":"hello",
"p":"universe"
"div":
"h1":"Heading 1",
"p":"another paragraph"
]
could then easily parse to html for example
<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.
Your first example’s array is missing a comma. Also, it is inconsistent with itself. If you’re going to use a dictionary as an ordered collection, your outer array should also just be an object. I.e.,
"div":"p":"hello","p":"universe", "div":"h1":"Heading 1","p":"another paragraph"
. Now, lots of people and frameworks treat JSON objects as unordered dictionaries, but JavaScript and e.g. MongoDB’s API rely on ordering of keys within dictionaries, so what you’re suggesting (ordered dictionaries) is not unheard of. You’d just need a specialized parser.– binki
Jul 6 '17 at 16:35
"div":"p":"hello","p":"universe", "div":"h1":"Heading 1","p":"another paragraph"
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."
If you're a gambler, "many" JSON engines will allow duplication and simply use the last-specified value. This:
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!
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.
From practical application, I have seen the value from the last key is considered when duplicate keys are found in a JSON.
In C# if you deserialise to a Dictionary<string, string>
it takes the last key value pair:
Dictionary<string, string>
string json = @"""a"": ""x"", ""a"": ""y""";
var d = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
// "a" : "y"
if you try to deserialise to
class Foo
[JsonProperty("a")]
public string Bar get; set;
[JsonProperty("a")]
public string Baz get; set;
var f = JsonConvert.DeserializeObject<Foo>(json);
you get a Newtonsoft.Json.JsonSerializationException
exception.
Newtonsoft.Json.JsonSerializationException
i guess that is what most (if not all) implementations do, but it doesnt answer my question if it is valid as of the specification of JSON.
– clamp
Feb 17 '14 at 15:30
@svidgen: This isn't even Microsoft's implementation... it's a third-party library.
– BoltClock♦
Apr 21 '14 at 10:18
@BoltClock Ah, touche.
– svidgen
Apr 21 '14 at 13:56
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.
The bug is in node.js at least. This code succeeds in node.js.
try
var json = "name":"n","name":"v";
console.log(json); // outputs name: 'v'
catch (e)
console.log(e);
It's not a bug, and section you quoted explains why it is not: different languages behave differently, and JSON parsers will do what's most natural for that language. In any case, this answer doesn't add anything that user454322 hasn't already said above.
– Richard Smith
Mar 28 '16 at 14:14
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
C# 's Json.NET removes the first key pair if you deserialise to a
Dictionary<string, string>
– Sam Leach
Feb 17 '14 at 15:20