Skip to content

fix: don't let case-insensitive fallback reuse an exactly-matched key#192

Open
koriyoshi2041 wants to merge 1 commit into
go-viper:mainfrom
koriyoshi2041:fix/case-insensitive-duplicate-key
Open

fix: don't let case-insensitive fallback reuse an exactly-matched key#192
koriyoshi2041 wants to merge 1 commit into
go-viper:mainfrom
koriyoshi2041:fix/case-insensitive-duplicate-key

Conversation

@koriyoshi2041

Copy link
Copy Markdown

Fixes #75.

When a struct has two fields whose names differ only by case, decoding a map that contains one of them populates both fields:

type Result struct {
    Name string `mapstructure:"name"`
    NAME string `mapstructure:"NAME"`
}
var r Result
mapstructure.Decode(map[string]any{"name": "lower"}, &r)
// got:  {Name:"lower" NAME:"lower"}
// want: {Name:"lower" NAME:""}

In decodeStructFromMap, the Name field matches the key "name" exactly and removes it from dataValKeysUnused. The NAME field has no exact key, so it falls into the case-insensitive search — which iterates all keys and matches "name" again via MatchName, even though it was already consumed. (encoding/json gives the value only to the exact match.)

The fix skips keys that are no longer in dataValKeysUnused during the case-insensitive fallback, so each map key is claimed by at most one field, and the exact match wins.

Added TestDecode_caseInsensitiveDuplicateKey; it fails before the fix (NAME is "lower") and passes after. Existing TestDecode* tests still pass.

When a struct has fields whose names differ only by case (e.g. `name` and
`NAME`) and the input map contains one of them (e.g. "name"), the field with
the exact match consumed the key and the case-insensitive fallback then
matched the same key again, populating both fields. Skip keys that another
field already removed from the unused set so each map key is consumed by at
most one field.
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.

[bug] Mapstructure handles fields with different case twice

1 participant