Skip to content

Add Decoder.AllowDuplicateKeys - #17

Open
reuvenharrison wants to merge 1 commit into
v3from
feat/allow-duplicate-keys
Open

Add Decoder.AllowDuplicateKeys#17
reuvenharrison wants to merge 1 commit into
v3from
feat/allow-duplicate-keys

Conversation

@reuvenharrison

Copy link
Copy Markdown
Collaborator

Why

A repeated mapping key is an error here, which is YAML's rule. encoding/json takes the last occurrence for a repeated JSON object name — RFC 8259 says names SHOULD be unique, so the handling is left to the implementation.

That difference is invisible until one program decodes both YAML and JSON into the same types. Then a document loads or fails depending only on which format it happens to be written in. Measured on the same content:

duplicate keys
encoding/json accepts, last wins
this package error: mapping key "title" already defined at line 3

The switch already exists internally (decoder.uniqueKeys, hard-coded true in newDecoder); it was simply never plumbed to the public Decoder.

What

Decoder.AllowDuplicateKeys(bool), wired the same way as KnownFields, Origin and DisableTimestamps.

Default is unchanged — repeated keys still error. Enabled, the last occurrence wins, matching encoding/json.

Tests

Six cases. They assert the surviving value rather than only the absence of an error, since "does not fail" would equally be satisfied by dropping the key or keeping the first, and neither matches encoding/json:

  • rejected by default (no call to the setter at all)
  • rejected when explicitly disallowed
  • last-one-wins when allowed, with the sibling key checked as untouched
  • the flag does not leak between decoders
  • a duplicate nested two levels down, both modes
  • decoding into a generic map as well as a struct, since mapping and mappingStruct are different paths in the decoder

Verified the suite actually exercises them by breaking an assertion and confirming the failure is caught (obtained "b"), not merely that the run stays green.

A repeated mapping key is an error here, which is YAML's rule, while
encoding/json takes the last occurrence (RFC 8259 says object names
SHOULD be unique, so the handling is the implementation's to choose).

That difference is invisible until one program decodes both formats into
the same types, at which point a document loads or fails depending only
on which format it happens to be written in. This exposes the existing
internal switch so such a caller can pick one answer for both.

The default is unchanged: repeated keys still error. Enabling the option
makes the last occurrence win, matching encoding/json.

Tests assert the surviving value rather than just the absence of an
error, since "does not fail" would equally be satisfied by dropping the
key or keeping the first, and neither matches encoding/json. They also
cover the struct and generic-map decode paths separately (different code
in the decoder), nesting, and that the flag does not leak between
decoders.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant