]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: correct caller's name in encoding errors
authorEugene Kalinin <e.v.kalinin@gmail.com>
Fri, 28 Jun 2019 20:59:49 +0000 (23:59 +0300)
committerIan Lance Taylor <iant@golang.org>
Wed, 16 Oct 2019 22:58:08 +0000 (22:58 +0000)
1. Change mapencode.encode to use fmt.Error rather than MarshalerError.
MarshalerError refer to MarshalJSON, but mapencode.encode does not use that.

2. Add sourceFunc field to MarshalerError to record the name of the function
that creates the error, so that the Error method can report it correctly.

Fixes #29753

Change-Id: I186c2fac8470ae2f9e300501de3730face642230
Reviewed-on: https://go-review.googlesource.com/c/go/+/184119
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/encoding/json/encode.go
src/encoding/json/encode_test.go

index b4fba476c82362e0da619c83a6dc0bb368098aeb..a7473a7eba5d9f208ac8314dd8d10e1a8c20f9f1 100644 (file)
@@ -261,14 +261,22 @@ func (e *InvalidUTF8Error) Error() string {
 
 // A MarshalerError represents an error from calling a MarshalJSON or MarshalText method.
 type MarshalerError struct {
-       Type reflect.Type
-       Err  error
+       Type       reflect.Type
+       Err        error
+       sourceFunc string
 }
 
 func (e *MarshalerError) Error() string {
-       return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error()
+       srcFunc := e.sourceFunc
+       if srcFunc == "" {
+               srcFunc = "MarshalJSON"
+       }
+       return "json: error calling " + srcFunc +
+               " for type " + e.Type.String() +
+               ": " + e.Err.Error()
 }
 
+// Unwrap returns the underlying error.
 func (e *MarshalerError) Unwrap() error { return e.Err }
 
 var hex = "0123456789abcdef"
@@ -455,7 +463,7 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
                err = compact(&e.Buffer, b, opts.escapeHTML)
        }
        if err != nil {
-               e.error(&MarshalerError{v.Type(), err})
+               e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
        }
 }
 
@@ -472,7 +480,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
                err = compact(&e.Buffer, b, opts.escapeHTML)
        }
        if err != nil {
-               e.error(&MarshalerError{v.Type(), err})
+               e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
        }
 }
 
@@ -488,7 +496,7 @@ func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
        }
        b, err := m.MarshalText()
        if err != nil {
-               e.error(&MarshalerError{v.Type(), err})
+               e.error(&MarshalerError{v.Type(), err, "MarshalText"})
        }
        e.stringBytes(b, opts.escapeHTML)
 }
@@ -502,7 +510,7 @@ func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
        m := va.Interface().(encoding.TextMarshaler)
        b, err := m.MarshalText()
        if err != nil {
-               e.error(&MarshalerError{v.Type(), err})
+               e.error(&MarshalerError{v.Type(), err, "MarshalText"})
        }
        e.stringBytes(b, opts.escapeHTML)
 }
@@ -761,7 +769,7 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
        for i, v := range keys {
                sv[i].v = v
                if err := sv[i].resolve(); err != nil {
-                       e.error(&MarshalerError{v.Type(), err})
+                       e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
                }
        }
        sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s })
index 8d3503b1ba23ea2acf99d2b910599a2ed6f773f3..40f16d86ff87522b83a6b0347d720adcc2143b39 100644 (file)
@@ -1064,3 +1064,30 @@ func TestMarshalUncommonFieldNames(t *testing.T) {
                t.Fatalf("Marshal: got %s want %s", got, want)
        }
 }
+
+func TestMarshalerError(t *testing.T) {
+       s := "test variable"
+       st := reflect.TypeOf(s)
+       errText := "json: test error"
+
+       tests := []struct {
+               err  *MarshalerError
+               want string
+       }{
+               {
+                       &MarshalerError{st, fmt.Errorf(errText), ""},
+                       "json: error calling MarshalJSON for type " + st.String() + ": " + errText,
+               },
+               {
+                       &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"},
+                       "json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
+               },
+       }
+
+       for i, tt := range tests {
+               got := tt.err.Error()
+               if got != tt.want {
+                       t.Errorf("MarshalerError test %d, got: %s, want: %s", i, got, tt.want)
+               }
+       }
+}