aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorEmmanuel Odeke <emm.odeke@gmail.com>2016-10-24 21:20:04 -0700
committerRuss Cox <rsc@golang.org>2016-11-11 14:50:51 +0000
commitadd721ef91ed533cf578ff7a604124e377329ae4 (patch)
tree25a6ef1a701978890f9ee87a9fdf4cc2578f2a66 /src/encoding
parentc439a5d8b77a3b87d94bc49714faeeb2a04112f4 (diff)
downloadgo-add721ef91ed533cf578ff7a604124e377329ae4.tar.xz
encoding/json: encode nil Marshaler as "null"
Fixes #16042. Change-Id: I0a28aa004246b7b0ffaaab457e077ad9035363c2 Reviewed-on: https://go-review.googlesource.com/31932 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/json/encode.go6
-rw-r--r--src/encoding/json/encode_test.go38
2 files changed, 43 insertions, 1 deletions
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 667df31ce3..98a9899502 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -443,7 +443,11 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
e.WriteString("null")
return
}
- m := v.Interface().(Marshaler)
+ m, ok := v.Interface().(Marshaler)
+ if !ok {
+ e.WriteString("null")
+ return
+ }
b, err := m.MarshalJSON()
if err == nil {
// copy JSON into buffer, checking validity.
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index b2c9e91dde..ebcf07cf38 100644
--- a/src/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -293,6 +293,44 @@ type BugX struct {
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.
func TestEmbeddedBug(t *testing.T) {
v := BugB{