What every JSON parser does with duplicate keys
The JSON specification permits duplicate keys and does not say which one wins. So every one of the 21 parsers tested accepts {"a":1,"a":2} without an error — and they do not all agree on the result.
No parser rejects it. Not all of them agree afterwards.
Of 21 parsers, 21 accept a duplicated key silently and none reject it. That is correct behaviour: RFC 8259 says names should be unique, not must, and leaves the outcome undefined.
The undefined part is the problem. Here is what comes back:
| Result | Parsers |
|---|---|
{"a":2} | Gson, Jackson ObjectMapper, JavaScriptCore JSON.parse, Newtonsoft.Json, Ruby JSON.parse, SpiderMonkey JSON.parse, V8 JSON.parse, encoding/json Unmarshal, json_decode |
{"a": 2} | CPython json.loads |
{"a":1,"a":2} | System.Text.Json |
Input: {"a":1,"a":2}, parsed then re-serialised.
System.Text.Json keeps both
Most parsers keep the last occurrence. System.Text.Json is different: a JsonDocument preserves the raw structure, so re-serialising gives you back {"a":1,"a":2} — both keys, still duplicated.
That matters if a .NET service sits in the middle of a pipeline. It will faithfully pass on a duplicate that the next hop resolves differently.
The failure mode is that nothing fails
Merged configuration fragments, hand-edited files, and templating loops all produce duplicate keys. Because no parser errors, the file "works" — it just uses one of the two values, and which one depends on the language reading it.
There is no parse error to catch. You have to look for it deliberately: Python's object_pairs_hook, a custom unmarshaller in Go, or a linter in CI.
Standards referenced
RFC 8259 §4 states that names within an object should be unique and describes the behaviour of receiving software as unpredictable when they are not. ECMA-404 §6 does not require uniqueness at all.
- RFC 8259 (STD 90) §4 — Objects — The JavaScript Object Notation (JSON) Data Interchange Format, T. Bray, Ed., 2017.
- ECMA-404, 2nd edition §objects — 6 Objects — The JSON Data Interchange Syntax, Ecma International, 2017.
Only standards bodies and peer-reviewed venues are cited here.
How this was measured
The same document was passed to every parser, the result re-serialised, and the output recorded. Error behaviour comes from a separate corpus of 50 malformed documents run through the same set.
Every figure on this page came from executing the parser named, not from documentation. The collection harness is public — see the error registry method notes.