Go version

go 1.24.4, macos arm

Output of go env in your module/workspace:

AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/******/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/******/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/q1/vkp7_jk55kq3d118jm2w9f600000gn/T/go-build3594624170=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/Users/******/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/******/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.24.4/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/******/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.24.4/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

package main

import (
    "encoding/json"
    "fmt"
)

type BinanceTick struct {
    EventType string      `json:"e"`
    EventTime int64       `json:"E"`
    Symbol    string      `json:"s"`
    Price     json.Number `json:"c"`
}

func main() {
    jsonData := `{"e":"24hrTicker","E":1752962976782,"s":"BBUSDT","p":"0.0131200","P":"12.485","w":"0.1169626","c":"0.1182100","Q":"1067","o":"0.1050900","h":"0.1258600","l":"0.1011300","v":"400610658","q":"46856448.9866300","O":1752876540000,"C":1752962976778"F":159151473,"L":159634704,"n":483180}`
    var ticker BinanceTick
    if err := json.Unmarshal([]byte(jsonData), &ticker); err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("%+v\n", ticker)
}

expected 0.1182100, get 1752962976778

What did you see happen?

Hi, it took me a week to find this bug in a project that will cause me to have to go part-time in a cab

There is a json response from the server example in jsonData, there is a structure in which we expect Price json.Number json: “c” (small letter), but we get the result {EventType:24hrTicker EventTime:1752962976782 Symbol:BBUSDT Price:1752962976778}, the data is taken from the big letter “C”.

If you set the string or float64 type for Price, you will get an unmarshal error

What did you expect to see?

data spoofing

Comment From: seankhliao

From the docs:

To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match.

Every incoming field is matched against the struct fields. json struct tags are in addition to the original field name, not the only name that will be used.

Closing as working as intended.

Comment From: devjkeee

From the docs:

To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match.

Every incoming field is matched against the struct fields. json struct tags are in addition to the original field name, not the only name that will be used.

Closing as working as intended.

this data comes from an external source, I can't change the keys.

Comment From: randall77

preferring an exact match but also accepting a case-insensitive match.

If you have both a C and a c field in your struct, you can parse your data correctly.