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.