]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: add Path to UnmarshalTypeError
authorLE Manh Cuong <cuong.manhle.vn@gmail.com>
Sat, 27 Oct 2018 18:44:09 +0000 (01:44 +0700)
committerDaniel Martí <mvdan@mvdan.cc>
Tue, 5 Mar 2019 12:34:11 +0000 (12:34 +0000)
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/+/145218
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/encoding/json/decode.go
src/encoding/json/decode_test.go

index 731553dca6b4833db215355888c14ffb771ad278..3900bcc165c5644e0dff1b96b2ea9423cd3bb2fd 100644 (file)
@@ -125,7 +125,7 @@ type UnmarshalTypeError struct {
        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       // name of the field holding the Go value
+       Field  string       // the full path from root node to the field
 }
 
 func (e *UnmarshalTypeError) Error() string {
@@ -730,7 +730,11 @@ func (d *decodeState) object(v reflect.Value) error {
                                        }
                                        subv = subv.Field(i)
                                }
-                               d.errorContext.Field = f.name
+                               if originalErrorContext.Field == "" {
+                                       d.errorContext.Field = f.name
+                               } else {
+                                       d.errorContext.Field = originalErrorContext.Field + "." + f.name
+                               }
                                d.errorContext.Struct = t
                        } else if d.disallowUnknownFields {
                                d.saveError(fmt.Errorf("json: unknown field %q", key))
index 60454c60583542ce4639635d35875992bfa3ccb7..d99d65d7634114218dcce8ee32498a8ae157bbb3 100644 (file)
@@ -45,6 +45,14 @@ type W struct {
        S SS
 }
 
+type P struct {
+       PP PP
+}
+
+type PP struct {
+       T T
+}
+
 type SS string
 
 func (*SS) UnmarshalJSON(data []byte) error {
@@ -816,7 +824,7 @@ var unmarshalTests = []unmarshalTest{
                err: &UnmarshalTypeError{
                        Value:  "string",
                        Struct: "V",
-                       Field:  "F2",
+                       Field:  "V.F2",
                        Type:   reflect.TypeOf(int32(0)),
                        Offset: 20,
                },
@@ -827,7 +835,7 @@ var unmarshalTests = []unmarshalTest{
                err: &UnmarshalTypeError{
                        Value:  "string",
                        Struct: "V",
-                       Field:  "F2",
+                       Field:  "V.F2",
                        Type:   reflect.TypeOf(int32(0)),
                        Offset: 30,
                },
@@ -923,6 +931,18 @@ var unmarshalTests = []unmarshalTest{
                ptr: new(MustNotUnmarshalText),
                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) {