Skip to content

Commit cc39d80

Browse files
wI2Lmvdan
authored andcommitted
encoding/json: encode nil encoding.TextMarshaler instance as "null"
Fixes #34235. Change-Id: Ia3795fd18860530fa6a4b171545f525e784ffdcb GitHub-Last-Rev: 1a319c4 GitHub-Pull-Request: #34238 Reviewed-on: https://go-review.googlesource.com/c/go/+/194642 Reviewed-by: Daniel Martí <[email protected]> Run-TryBot: Daniel Martí <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 85c60bd commit cc39d80

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

src/encoding/json/encode.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,11 @@ func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
481481
e.WriteString("null")
482482
return
483483
}
484-
m := v.Interface().(encoding.TextMarshaler)
484+
m, ok := v.Interface().(encoding.TextMarshaler)
485+
if !ok {
486+
e.WriteString("null")
487+
return
488+
}
485489
b, err := m.MarshalText()
486490
if err != nil {
487491
e.error(&MarshalerError{v.Type(), err})

src/encoding/json/encode_test.go

+24-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package json
66

77
import (
88
"bytes"
9+
"encoding"
910
"fmt"
1011
"log"
1112
"math"
@@ -453,18 +454,31 @@ type BugX struct {
453454
BugB
454455
}
455456

456-
// Issue 16042. Even if a nil interface value is passed in
457-
// as long as it implements MarshalJSON, it should be marshaled.
458-
type nilMarshaler string
457+
// golang.org/issue/16042.
458+
// Even if a nil interface value is passed in, as long as
459+
// it implements Marshaler, it should be marshaled.
460+
type nilJSONMarshaler string
459461

460-
func (nm *nilMarshaler) MarshalJSON() ([]byte, error) {
462+
func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {
461463
if nm == nil {
462464
return Marshal("0zenil0")
463465
}
464466
return Marshal("zenil:" + string(*nm))
465467
}
466468

467-
// Issue 16042.
469+
// golang.org/issue/34235.
470+
// Even if a nil interface value is passed in, as long as
471+
// it implements encoding.TextMarshaler, it should be marshaled.
472+
type nilTextMarshaler string
473+
474+
func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
475+
if nm == nil {
476+
return []byte("0zenil0"), nil
477+
}
478+
return []byte("zenil:" + string(*nm)), nil
479+
}
480+
481+
// See golang.org/issue/16042 and golang.org/issue/34235.
468482
func TestNilMarshal(t *testing.T) {
469483
testCases := []struct {
470484
v interface{}
@@ -478,8 +492,11 @@ func TestNilMarshal(t *testing.T) {
478492
{v: []byte(nil), want: `null`},
479493
{v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
480494
{v: struct{ M Marshaler }{}, want: `{"M":null}`},
481-
{v: struct{ M Marshaler }{(*nilMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
482-
{v: struct{ M interface{} }{(*nilMarshaler)(nil)}, want: `{"M":null}`},
495+
{v: struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
496+
{v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`},
497+
{v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`},
498+
{v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
499+
{v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
483500
}
484501

485502
for _, tt := range testCases {

0 commit comments

Comments
 (0)