Guide

How to find duplicate keys in JSON

Duplicate JSON member names are a source-text problem: once ordinary JavaScript parsing has happened, the earlier value is already gone. The JSON Validator is useful here because it parses the document for normal syntax errors and, by default, separately scans the original text for repeated names within the same object.

That scan is a review aid, not a replacement for a schema or a security policy. JSON RFC 8259 says names within an object SHOULD be unique, and implementations differ when they are not. In this tool, `JSON.parse` retains the last value, so a validator warning flags a possible overwrite to inspect. Its heuristic scanner can miss escaped equivalent names or report different names as duplicates; it is not a proof of uniqueness.

Open the JSON Validator

Use this when


  • A configuration value seems to vanish after a JSON file is loaded
  • A template, merge script or hand edit may have emitted the same property twice
  • You need to review an API fixture before formatting or converting it
  • A security-sensitive field such as role, issuer or redirect URL must occur once
  • You need a concise report of duplicate names for a code review

What the validator actually does


The tool first calls `JSON.parse`. Invalid JSON stops there and reports an error, with a location when the parser provides one; a duplicate-key report is meaningful only after the document is syntactically valid. It then calculates a structural summary and, while the “Report duplicate keys” option remains on, scans the raw input for repeated quoted names in each object scope.

The option is on by default. When matches are found, the result lists up to twenty `line N: "key" (in the same object)` entries and adds a warning with the total. The output is not a rewritten JSON document, so it does not pretend to preserve both values. It is an instruction to repair the source before any parse-and-serialize step decides which value wins.

Turn the option off only when you need the structural summary and have already checked the source another way. Disabling it does not make duplicates safe; it merely omits this scanner. Formatting, minifying, JSON-to-CSV conversion and any other tool based on `JSON.parse` still see only the final parsed property.

{
  "theme": "light",
  "theme": "dark"
}
With duplicate reporting enabled, expect a duplicate `theme` entry on line 3. The parsed JavaScript value has only `"theme": "dark"`.

Why the last value wins in this tool


JavaScript object properties have one value per name. During `JSON.parse`, a later member with the same name assigns that property again, replacing the earlier one. That makes the following input appear harmless after parsing: the output contains `timeout: 30`, but no normal object walk can prove that `timeout: 10` was present in the source first.

The order matters. In a generated document, a harmless default followed by a malicious or mistaken override can be treated differently by a different parser, proxy, validator or application. That disagreement is the real operational problem. “Last wins” describes this JavaScript implementation, not a portable guarantee you should rely on across systems.

Repair the producer rather than keeping a convention about which occurrence is authoritative. A review comment such as “keep the second one” leaves the next edit free to reverse their order. One name, one definition, and a test for the intended parsed value are substantially clearer.

Source member orderThis tool after JSON.parseSafe action
`"timeout": 10`, then `"timeout": 30``timeout` is 30Keep one deliberate value
`"role": "user"`, then `"role": "admin"``role` is adminReject and fix the producer
Same name in separate nested objectsBoth properties remainUsually valid; their scopes differ

Scope matters: nested names are not duplicates


A duplicate is two occurrences in the same object. Reusing a common name such as `id`, `name` or `enabled` in different objects is ordinary JSON and should not be renamed merely to satisfy a global search. The scanner tracks object braces as scopes so a top-level `id` and a nested `user.id` are treated independently.

Arrays do not create property names themselves, but objects inside arrays each have their own scope. Two array records can both contain `id`; that is the normal table-like shape. A repeated `id` inside one of those record objects is the case to fix. Read the reported line alongside the surrounding braces before changing anything.

This distinction is especially important with copied configuration blocks. A copied object can legitimately contain the same keys as its sibling. A merge that accidentally places both blocks’ contents into one object creates duplicates. The source may look nearly identical, while the braces decide whether the document has two records or one ambiguous record.

{
  "id": "request-1",
  "user": { "id": "user-9" },
  "items": [{ "id": 1 }, { "id": 2 }]
}
This contains four `id` names in separate object scopes and should not produce a duplicate-key finding.

Know the raw-scanner limitations


The duplicate report scans text because parsing has already erased earlier values. Its scanner is simpler than a full JSON tokenizer: it skips a backslash and the following character rather than decoding that escape. Consequently, different spellings that decode to the same property name can evade the report, and names that are actually different can be reported as duplicates.

For example, `"a"` and `"\u0061"` decode to the same JavaScript property name, but the scanner compares `a` with `0061` and misses the duplicate. Conversely, `"ab"` and `"a\nb"` compare as `ab` in the scanner even though the second decoded key contains a newline. Do not remove one solely because of that warning: inspect the actual decoded names. A clean report is useful evidence for ordinary names, not a proof of uniqueness for hostile or heavily escaped input.

The scanner also reports at most twenty individual lines while retaining the total in its warning. For a generated document with many matches, fix the template or generator and run it again; do not treat the first twenty as the whole defect list. If uniqueness is a security boundary, use a parser or validation layer designed to reject duplicate decoded keys before application parsing.

{
  "a": 1,
  "\u0061": 2
}
Both names decode to `a` in JSON. The tool’s raw duplicate scanner can miss this escaped-name case, so use a stricter ingestion validator when uniqueness is security-critical.

A review sequence that preserves evidence


Start with the original file, not a formatted copy. Run the JSON Validator with duplicate reporting enabled and save the source somewhere reviewable if the data matters. Read any duplicate lines in context, decide the intended value with the data owner, then delete or rename the unintended member in the producer.

Run the validator again. A valid result with no duplicate report is not a safety guarantee: review escaped names and precision-sensitive numbers before formatting. The JSON Formatter still parses and serializes, so it is excellent for a readable diff after the source problem is removed, but it cannot recover an earlier member that was discarded beforehand.

Finally, test the consumer’s expectation. Syntax validation cannot tell you whether `timeout` belongs at the top level, whether a URL is allowed, or whether a role is permitted. A JSON Schema or application-level test covers those semantic rules; duplicate-key detection protects the narrower but important rule that there is one unambiguous spelling of each property in an object.

  • Validate the untouched source with “Report duplicate keys” enabled.
  • Inspect each reported line in its object scope.
  • Fix the template, merge step or editor action that emitted the duplicate.
  • Validate again before formatting or converting.
  • Add schema or application tests for the meaning of the retained value.

RFC 8259, Section 4: Objects — The primary JSON specification recommends unique object names and explains that duplicate behavior is unpredictable across implementations.

Common problems


Each of these is something that actually happens, with the cause rather than a generic suggestion to check your input.

Formatting removed a value I can see in the original file

Cause
The key appeared more than once and `JSON.parse` retained the later member before the formatter serialized the object.
Fix
Return to the original text, validate it with duplicate reporting enabled, and keep one intended member.

The validator says the JSON is valid but warns about duplicates

Cause
Duplicate names are syntactically accepted by this parser even though they are unsafe for interoperable data.
Fix
Treat the warning as a source defect, not as permission to depend on last-wins behavior.

A global search finds many repeated names but the tool finds none

Cause
The occurrences are in separate nested objects or array records, where reuse is normal.
Fix
Check braces and scopes. Only repeated names within one object are duplicate members.

A security review needs proof escaped names are unique

Cause
The built-in report is a raw-text scanner and can miss differently escaped spellings of the same decoded key.
Fix
Use a strict parser or gateway that rejects duplicate decoded keys before the application sees the document.

Questions


Does valid JSON require every key to be unique?
RFC 8259 says object names SHOULD be unique for interoperability. This tool accepts syntactically valid duplicate names because JavaScript parsing does, then warns by default so the source can be repaired.
Which duplicate value does this tool keep?
JavaScript `JSON.parse` keeps the last member for a repeated name. Do not treat that as a cross-language contract; other implementations can reject duplicates or handle them differently.
Can the tool find every duplicate?
No. It catches ordinary repeated raw key spellings in the same object, but it is not a full decoded-key uniqueness validator. Escaped equivalent names such as `"a"` and `"\u0061"` can be missed.
Should I format before validating?
Validate the original first. Formatting parses and serializes, so an earlier duplicate member may already be unrecoverable by the time you inspect the formatted output.