Commit 29bc4f12 authored by LE Manh Cuong's avatar LE Manh Cuong Committed by Daniel Martí

encoding/json: add Path to UnmarshalTypeError

When parsing nested object, UnmarshalTypeError does not contain actual
path to nested field in original JSON.

This commit change Field to contain the full path to that field. One
can get the Field name by stripping all the leading path elements.

Fixes #22369

Change-Id: I6969cc08abe8387a351e3fb2944adfaa0dccad2a
Reviewed-on: https://go-review.googlesource.com/c/go/+/145218Reviewed-by: default avatarDaniel Martí <mvdan@mvdan.cc>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 95d4e615
...@@ -125,7 +125,7 @@ type UnmarshalTypeError struct { ...@@ -125,7 +125,7 @@ type UnmarshalTypeError struct {
Type reflect.Type // type of Go value it could not be assigned to Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes Offset int64 // error occurred after reading Offset bytes
Struct string // name of the struct type containing the field Struct string // name of the struct type containing the field
Field string // name of the field holding the Go value Field string // the full path from root node to the field
} }
func (e *UnmarshalTypeError) Error() string { func (e *UnmarshalTypeError) Error() string {
...@@ -730,7 +730,11 @@ func (d *decodeState) object(v reflect.Value) error { ...@@ -730,7 +730,11 @@ func (d *decodeState) object(v reflect.Value) error {
} }
subv = subv.Field(i) subv = subv.Field(i)
} }
if originalErrorContext.Field == "" {
d.errorContext.Field = f.name d.errorContext.Field = f.name
} else {
d.errorContext.Field = originalErrorContext.Field + "." + f.name
}
d.errorContext.Struct = t d.errorContext.Struct = t
} else if d.disallowUnknownFields { } else if d.disallowUnknownFields {
d.saveError(fmt.Errorf("json: unknown field %q", key)) d.saveError(fmt.Errorf("json: unknown field %q", key))
......
...@@ -45,6 +45,14 @@ type W struct { ...@@ -45,6 +45,14 @@ type W struct {
S SS S SS
} }
type P struct {
PP PP
}
type PP struct {
T T
}
type SS string type SS string
func (*SS) UnmarshalJSON(data []byte) error { func (*SS) UnmarshalJSON(data []byte) error {
...@@ -816,7 +824,7 @@ var unmarshalTests = []unmarshalTest{ ...@@ -816,7 +824,7 @@ var unmarshalTests = []unmarshalTest{
err: &UnmarshalTypeError{ err: &UnmarshalTypeError{
Value: "string", Value: "string",
Struct: "V", Struct: "V",
Field: "F2", Field: "V.F2",
Type: reflect.TypeOf(int32(0)), Type: reflect.TypeOf(int32(0)),
Offset: 20, Offset: 20,
}, },
...@@ -827,7 +835,7 @@ var unmarshalTests = []unmarshalTest{ ...@@ -827,7 +835,7 @@ var unmarshalTests = []unmarshalTest{
err: &UnmarshalTypeError{ err: &UnmarshalTypeError{
Value: "string", Value: "string",
Struct: "V", Struct: "V",
Field: "F2", Field: "V.F2",
Type: reflect.TypeOf(int32(0)), Type: reflect.TypeOf(int32(0)),
Offset: 30, Offset: 30,
}, },
...@@ -923,6 +931,18 @@ var unmarshalTests = []unmarshalTest{ ...@@ -923,6 +931,18 @@ var unmarshalTests = []unmarshalTest{
ptr: new(MustNotUnmarshalText), ptr: new(MustNotUnmarshalText),
err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1}, err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
}, },
// #22369
{
in: `{"PP": {"T": {"Y": "bad-type"}}}`,
ptr: new(P),
err: &UnmarshalTypeError{
Value: "string",
Struct: "T",
Field: "PP.T.Y",
Type: reflect.TypeOf(int(0)),
Offset: 29,
},
},
} }
func TestMarshal(t *testing.T) { func TestMarshal(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment