]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: add embedded structs to the UnmarshalTypeError's Field
authorj2gg0s <j2gg0s@gmail.com>
Tue, 27 Aug 2024 14:35:59 +0000 (14:35 +0000)
committerGopher Robot <gobot@golang.org>
Tue, 3 Sep 2024 15:49:47 +0000 (15:49 +0000)
Including embedded struct inforamtion in error message.

Fixes #68941

Change-Id: I6a6f7d506104839a9a7cf1a2c3003272f5534a79
GitHub-Last-Rev: 717f680acafd3f6509c0495f9092e028be502750
GitHub-Pull-Request: golang/go#68966
Reviewed-on: https://go-review.googlesource.com/c/go/+/606956
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
doc/next/6-stdlib/99-minor/encoding/json/68941.md [new file with mode: 0644]
src/encoding/json/decode.go
src/encoding/json/decode_test.go

diff --git a/doc/next/6-stdlib/99-minor/encoding/json/68941.md b/doc/next/6-stdlib/99-minor/encoding/json/68941.md
new file mode 100644 (file)
index 0000000..c7abec8
--- /dev/null
@@ -0,0 +1 @@
+[UnmarshalTypeError.Field] now includes embedded structs to provide more detailed error messages.
index 19d4563e33f27a4c191aadaa35f6187c6eba9bc2..1a05ef59a2c5345f8b03489ea3878b7cf36cbe95 100644 (file)
@@ -127,7 +127,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       // the full path from root node to the field
+       Field  string       // the full path from root node to the field, include embedded struct
 }
 
 func (e *UnmarshalTypeError) Error() string {
@@ -701,7 +701,10 @@ func (d *decodeState) object(v reflect.Value) error {
                        if f != nil {
                                subv = v
                                destring = f.quoted
-                               for _, i := range f.index {
+                               if d.errorContext == nil {
+                                       d.errorContext = new(errorContext)
+                               }
+                               for i, ind := range f.index {
                                        if subv.Kind() == reflect.Pointer {
                                                if subv.IsNil() {
                                                        // If a struct embeds a pointer to an unexported type,
@@ -721,13 +724,16 @@ func (d *decodeState) object(v reflect.Value) error {
                                                }
                                                subv = subv.Elem()
                                        }
-                                       subv = subv.Field(i)
-                               }
-                               if d.errorContext == nil {
-                                       d.errorContext = new(errorContext)
+                                       if i < len(f.index)-1 {
+                                               d.errorContext.FieldStack = append(
+                                                       d.errorContext.FieldStack,
+                                                       subv.Type().Field(ind).Name,
+                                               )
+                                       }
+                                       subv = subv.Field(ind)
                                }
-                               d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
                                d.errorContext.Struct = t
+                               d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
                        } else if d.disallowUnknownFields {
                                d.saveError(fmt.Errorf("json: unknown field %q", key))
                        }
index 752825cffeac4f2327435d01e432cd681b52cca2..71895a9bb14d39dbe6a8f36db990aceb91a92b12 100644 (file)
@@ -898,6 +898,19 @@ var unmarshalTests = []struct {
                },
        },
 
+       {
+               CaseName: Name(""),
+               in:       `{"Level1a": "hello"}`,
+               ptr:      new(Top),
+               err: &UnmarshalTypeError{
+                       Value:  "string",
+                       Struct: "Top",
+                       Field:  "Embed0a.Level1a",
+                       Type:   reflect.TypeFor[int](),
+                       Offset: 10,
+               },
+       },
+
        // issue 15146.
        // invalid inputs in wrongStringTests below.
        {CaseName: Name(""), in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true},