1
0
mirror of https://github.com/golang/go synced 2024-11-18 05:04:47 -07:00

encoding/json: correct caller's name in encoding errors

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>
This commit is contained in:
Eugene Kalinin 2019-06-28 23:59:49 +03:00 committed by Ian Lance Taylor
parent 943df4f629
commit 02196d3657
2 changed files with 43 additions and 8 deletions

View 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 })

View 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)
}
}
}