Developer tools · JSON formatter & validator
Duplicate keys in JSON: what RFC 8259 allows and what parsers do
· Background
json standards validation
JSON's grammar permits the same key twice, the spec only says names 'should' be unique, and parsers disagree about which value wins. This post explains why that matters for correctness and security.
Which 'role' did the server read?
Consider `{"role":"viewer","role":"editor"}`. Both members are grammatically complete, so ToolAcre reports valid JSON. When the text reaches `JSON.parse`, the resulting object has one `role` property whose value is `"editor"`. The earlier member is not retained as hidden history. A successful syntax check therefore answers nothing about whether object names appeared more than once.
Formatting makes the loss visible only after it has happened: the output contains `{"role":"editor"}` in the chosen layout. It cannot reproduce the discarded `viewer` member because serialization receives the parsed object, not the original member sequence. If repeated names matter to a review, preserve and inspect the source text before pressing Format rather than relying on the normalized result.
The grammar allows it, the spec discourages it
RFC 8259 says names within an object should be unique. That “should” promotes interoperable output without making uniqueness part of the basic object grammar. A repeated name still consists of a valid string, colon and value in the correct comma-separated position. Consequently, a grammar validator can accept the document while an application policy rejects it.
This distinction is easy to miss because many errors are mandatory syntax failures: a missing colon or trailing comma cannot form a JSON object at all. Duplicates are different. They create an interoperability question after the parser recognizes every token. ToolAcre intentionally stops at syntax and does not add a duplicate-name rule, so its Valid result must not be read as a uniqueness guarantee.
What JSON.parse and ToolAcre do
`JSON.parse` uses the later occurrence when object names repeat. ToolAcre inherits that behavior because it parses before formatting. For `{"limit":10,"limit":25,"unit":"items"}`, validation succeeds, the parsed limit is 25, and formatted output contains one `limit`. Optional key sorting can reposition that surviving property but cannot expose the overwritten occurrence.
Do not generalize that result to every parser or configuration. Some systems can reject duplicates, and other processing stacks may apply a different policy or inspect tokens before constructing an object. The safe cross-system statement is narrow: repeated names are not reliably interoperable. Check the actual parser modes used at each boundary when the distinction matters, rather than relying on a language-wide claim.
When parser disagreement becomes a risk
Duplicates become a security concern only in a concrete multi-stage path where components interpret the same text differently. For example, a request filter might inspect one occurrence while the application consumes another. Whether that can happen depends on the exact parsers, options, forwarding behavior and field use. Duplicate syntax alone does not prove an exploitable bypass.
The defensible control is to establish one policy at the trust boundary and test the real stack. Reject duplicate names before lossy object construction when ambiguity is unacceptable, or ensure every component receives the same already-parsed representation. ToolAcre can demonstrate its own last-wins formatting behavior, but it cannot audit gateways, frameworks or services that are not part of the browser tool.
Worked example: a document with a repeated key
Paste `{"theme":"light","prefs":{"density":"roomy","density":"compact"},"theme":"dark"}`. ToolAcre accepts the text because every member is syntactically valid. Parsing leaves the root theme as `dark` and the nested density as `compact`. Formatting emits one copy of each name, so both earlier values disappear from the displayed document.
That example also shows why searching the formatted result is too late. Duplicate detection must observe member names while reading the original token stream, at every object depth. Arrays need no duplicate-name rule, although separate application rules may care about repeated element values. Keep the source unchanged, run a duplicate-aware parser or linter against it, and decide whether the policy is warning or rejection.
Detecting duplicates on purpose
Use tooling that explicitly promises duplicate-name detection on source JSON. Suitable approaches include a parser mode that fails on repeats, a streaming token handler that tracks names for each open object, or a linter with a documented duplicate-key rule. Verify nested objects and escaped names: `"name"` and `"name"` decode to the same member name even though their source spellings differ.
JSON Schema is not a substitute once ordinary parsing has discarded earlier occurrences. A schema validator commonly receives the constructed value and sees one property, not the duplicate token history. Run uniqueness checking before or during parsing, then apply schema checks to the unambiguous value. ToolAcre performs neither duplicate detection nor schema validation, so both require a separate, purpose-built step.
What this does not cover
Repeated object names are not the same as repeated values across records. `[ {"id":7}, {"id":7} ]` contains two separate objects, each with one `id`; detecting a duplicate identifier there is a dataset rule. Likewise, two array elements with the same string remain two intentional positions unless an application contract says the array represents a set.
This article does not claim a universal first-wins, last-wins or reject policy for broad language ecosystems. It records ToolAcre’s observable `JSON.parse` behavior and explains why another component must be checked directly. It also does not determine exploitability from a duplicate alone. Security impact requires evidence that differing interpretations cross a relevant authorization, routing or validation boundary.
Takeaway: valid JSON is not always unambiguous JSON
A ToolAcre Valid result means the token sequence is strict JSON; it does not mean every object name is unique. `JSON.parse` keeps the last value for a repeated name, and formatting serializes only that survivor. Because the earlier occurrence is erased, formatted output is unsuitable evidence for deciding whether the original source contained duplicates.
When uniqueness matters, inspect the original text with duplicate-aware tooling before ordinary parsing or formatting. Apply schema and domain validation afterward to the resulting unambiguous value. For security review, trace the actual request path and parser settings instead of assuming disagreement. The practical rule is simple: syntax acceptance, duplicate-name policy and downstream meaning are separate checks with separate evidence.