Duplicate keys in JSON: why they parse, and why they are a bug

The JSON standard says object keys “should” be unique but does not forbid repeats, so most parsers accept them and quietly keep the last value. Some strict parsers, linters and editors reject them. Either way a duplicate means one value is being thrown away, which is almost never intended. PasteKit formats the document but flags every repeated key as a warning.

Seen as:

  • Duplicate key "timeout" — most parsers keep only the last value
  • Duplicate object key
  • com.fasterxml.jackson.core.JsonParseException: Duplicate field 'timeout'
  • System.ArgumentException: An item with the same key has already been added. Key: timeout

Input

Settings

History

Load from URL

Common causes

1. A setting added again instead of edited

In long config files it is easy to add "timeout": 5 at the bottom without noticing an existing "timeout": 30 near the top. JavaScript and Python keep 5; a reader of the file sees 30 first.

Before
{"timeout": 30, "retries": 3, "timeout": 5}
After
{"timeout": 5, "retries": 3}

2. Merging two versions of a file

Resolving a merge conflict by keeping both sides duplicates every key that changed. Look at both values and keep the one you mean.

Before
{
  "version": "2.3.0",
  "name": "web",
  "version": "2.4.0"
}
After
{
  "name": "web",
  "version": "2.4.0"
}

3. Repeated fields from another format

Query strings (?tag=a&tag=b), XML elements and HTTP headers can repeat a name. Mapping them to JSON key by key creates duplicates and loses all but one value; collect them into an array instead.

Before
{"tag": "sale", "tag": "winter", "tag": "outlet"}
After
{"tag": ["sale", "winter", "outlet"]}

4. JSON generated by string concatenation

Code that appends "key": value pairs in a loop writes the same key twice when the input has two rows for it. Building a dictionary first makes the overwrite visible in code, where it can be handled.

Before
parts = [f'"{k}": {json.dumps(v)}' for k, v in rows]
body = "{" + ", ".join(parts) + "}"
After
body = json.dumps(dict(rows))

Frequently asked questions

Are duplicate keys valid JSON?

Technically yes: RFC 8259 says names within an object SHOULD be unique, not MUST. But it also warns that behaviour is unpredictable when they are not, so treat duplicates as an error.

Which value wins?

JavaScript JSON.parse, Python json, Go encoding/json and jq all keep the last value. Some parsers keep the first, and some raise an error, which is why the same file can behave differently in two services.

Are "Name" and "name" duplicates?

No. JSON keys are compared exactly, so different capitalisation or a trailing space makes a different key. Case-insensitive deserializers, such as some .NET and Java settings, may still map both to the same field.

How do I make Python reject duplicate keys?

Pass object_pairs_hook to json.loads with a function that receives the list of key/value pairs and raises an error when a key appears twice.

Related