go
go copied to clipboard
encoding/json: wrong type name used in UnmarshalTypeError
Go version
go version go1.22.4 darwin/arm64
Output of go env in your module/workspace:
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/j2gg0s/Library/Caches/go-build'
GOENV='/Users/j2gg0s/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/j2gg0s/go/pkg/mod'
GONOPROXY='dev.msh.team,ohai.bot,github.com/j2gg0s'
GONOSUMDB='dev.msh.team,ohai.bot,github.com/j2gg0s'
GOOS='darwin'
GOPATH='/Users/j2gg0s/go'
GOPRIVATE='dev.msh.team,ohai.bot,github.com/j2gg0s'
GOPROXY='https://goproxy.cn,direct'
GOROOT='/Users/j2gg0s/sdk/go1.22.4'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='go1.22.4'
GOTOOLDIR='/Users/j2gg0s/sdk/go1.22.4/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.4'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/j2gg0s/gosrc/src/go.mod'
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 -ffile-prefix-map=/var/folders/3g/291pfdd54f11rlb15_hbq1dr0000gn/T/go-build1558397162=/tmp/go-build -gno-record-gcc-switches -fno-common'
What did you do?
package main
import (
"encoding/json"
"fmt"
)
type Y struct {
ZField int
}
type X struct {
YField Y
}
func ExampleUnmarshalTypeError() {
x := X{}
if err := json.Unmarshal([]byte(`{"YField": {"ZField": "hello"}}`), &x); err != nil {
fmt.Println(err)
}
// Output:
// json: cannot unmarshal string into Go struct field Y.YField.ZField of type int
}
What did you see happen?
Error's message is json: cannot unmarshal string into Go struct field Y.YField.ZField of type int
What did you expect to see?
Error's message should bejson: cannot unmarshal string into Go struct field X.YField.ZField of type int
If my understanding is correct, can I submit a PR to fix this issue?
Related Issues and Documentation
- encoding/json: nested unmarshaling mangles errors #68750 (closed)
- encoding/json: UnmarshalTypeError is clobbered when using nested custom marshallers #61337 (closed)
- encoding/json: UnmarshalJSON not working consistently with struct embedding #39175 (closed)
- encoding/json: UnmarshalTypeError Offset is broken if a nested struct implements UnmarshalJSON #43686 (closed)
- encoding/json: Decoding returns error when case-insensitive keys overlap and not all struct fields defined #54404 (closed)
- encoding/json: unmarshaler doesn't find UnmarshalJSON on embedded anonymous struct #46516
- encoding/json does not unmarshal my struct properly #63161 (closed)
- One more point #42519 (closed)
- encoding/json: promoted Unmarshal method on embedded field caused confusion #39470 (closed)
- encoding/json: json encoder fails for embedded non-struct fields #4474 (closed)
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Additional information about the solution.
Can we insert the Struct as the first element of the Field and no longer maintain the Struct field.
decode.go#L123
// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
Value string // description of JSON value - "bool", "array", "number -5"
Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes
Struct string // name of the struct type containing the field
Field string // the full path from root node to the field
}
Change https://go.dev/cl/606956 mentions this issue: encoding/json: print correct field path in UnmarshalTypeError
At the same time, we also lose the embedded struct information.
package main
import (
"encoding/json"
"fmt"
)
type Y struct {
ZField int
}
type X struct {
YField Y
}
type A struct {
IntField int
}
type B struct {
A
}
type C struct {
B
}
func ExampleUnmarshalTypeError() {
x := X{}
if err := json.Unmarshal([]byte(`{"YField": {"ZField": "hello"}}`), &x); err != nil {
fmt.Println(err)
}
c := C{}
if err := json.Unmarshal([]byte(`{"IntField": "hello"}`), &c); err != nil {
fmt.Println(err)
}
// Output:
// json: cannot unmarshal string into Go struct field Y.YField.ZField of type int
// json: cannot unmarshal string into Go struct field C.IntField of type int
}