Skip to content

Go json.Unmarshal documentation is misleading about case-insensitive key matching #73155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vaibhavgholap23 opened this issue Apr 3, 2025 · 2 comments
Labels
Documentation Issues describing a change to documentation.

Comments

@vaibhavgholap23
Copy link

Go version

go1.21.4 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=""
GOARCH="arm64"
GOBIN="/Users/gopher/go/bin"
GOCACHE="/Users/gopher/go/cache"
GOENV="/Users/gopher/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/gopher/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/gopher/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.21.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/44/nbbyll_10jd0z8rj_qxm43740000gn/T/go-build2331607515=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I ran the following Go program to test how json.Unmarshal handles case-insensitive JSON keys:

`package main

import (
"encoding/json"
"fmt"
)

type Example struct {
Name string json:"name"
}

func main() {
jsonData := {"name": "Alice", "NAME": "Bob", "Name": "Charlie"}

var e Example
err := json.Unmarshal([]byte(jsonData), &e)
if err != nil {
	fmt.Println("Error:", err)
	return
}

fmt.Println("Result:", e.Name) // Expected: "Alice", Actual: "Charlie"

}`

What did you see happen?

Instead of selecting the first exact match (i.e., "name": "Alice"), json.Unmarshal took the last occurrence of the key, "Name": "Charlie", regardless of case.

Result: Charlie

What did you expect to see?

The Go documentation suggests that json.Unmarshal prefers exact matches first before falling back to case-insensitive matching.

I expected the output to be:
Result: Alice

since "name" is an exact match to the struct tag.

Instead, Go appears to always take the last occurrence in JSON, regardless of case.

@gopherbot gopherbot added the Documentation Issues describing a change to documentation. label Apr 3, 2025
@vaibhavgholap23
Copy link
Author

Thank you for reviewing this issue! Since this behavior is confirmed, could we update the official encoding/json documentation to clearly state that:

json.Unmarshal does not prioritize exact matches first.

Instead, it follows a last key wins approach, regardless of case.

This clarification would help developers avoid confusion when handling JSON data with duplicate keys in different cases.

Please let me know your thoughts on this! Thanks again for your time. 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation Issues describing a change to documentation.
Projects
None yet
Development

No branches or pull requests

4 participants