Commit add721ef authored by Emmanuel Odeke's avatar Emmanuel Odeke Committed by Russ Cox

encoding/json: encode nil Marshaler as "null"

Fixes #16042.

Change-Id: I0a28aa004246b7b0ffaaab457e077ad9035363c2
Reviewed-on: https://go-review.googlesource.com/31932Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent c439a5d8
...@@ -443,7 +443,11 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { ...@@ -443,7 +443,11 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
e.WriteString("null") e.WriteString("null")
return return
} }
m := v.Interface().(Marshaler) m, ok := v.Interface().(Marshaler)
if !ok {
e.WriteString("null")
return
}
b, err := m.MarshalJSON() b, err := m.MarshalJSON()
if err == nil { if err == nil {
// copy JSON into buffer, checking validity. // copy JSON into buffer, checking validity.
......
...@@ -293,6 +293,44 @@ type BugX struct { ...@@ -293,6 +293,44 @@ type BugX struct {
BugB BugB
} }
// Issue 16042. Even if a nil interface value is passed in
// as long as it implements MarshalJSON, it should be marshaled.
type nilMarshaler string
func (nm *nilMarshaler) MarshalJSON() ([]byte, error) {
if nm == nil {
return Marshal("0zenil0")
}
return Marshal("zenil:" + string(*nm))
}
// Issue 16042.
func TestNilMarshal(t *testing.T) {
testCases := []struct {
v interface{}
want string
}{
{v: nil, want: `null`},
{v: new(float64), want: `0`},
{v: []interface{}(nil), want: `null`},
{v: []string(nil), want: `null`},
{v: map[string]string(nil), want: `null`},
{v: []byte(nil), want: `null`},
{v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
{v: struct{ M Marshaler }{}, want: `{"M":null}`},
{v: struct{ M Marshaler }{(*nilMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
{v: struct{ M interface{} }{(*nilMarshaler)(nil)}, want: `{"M":null}`},
}
for _, tt := range testCases {
out, err := Marshal(tt.v)
if err != nil || string(out) != tt.want {
t.Errorf("Marshal(%#v) = %#q, %#v, want %#q, nil", tt.v, out, err, tt.want)
continue
}
}
}
// Issue 5245. // Issue 5245.
func TestEmbeddedBug(t *testing.T) { func TestEmbeddedBug(t *testing.T) {
v := BugB{ v := BugB{
......
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