diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 7e5e209b4f..f10124e67d 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -629,12 +629,12 @@ type structEncoder struct { func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { next := byte('{') +FieldLoop: for i := range se.fields { f := &se.fields[i] // Find the nested struct field by following f.index. fv := v - FieldLoop: for _, i := range f.index { if fv.Kind() == reflect.Ptr { if fv.IsNil() { diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go index 1b7838c895..cd5eadf3c1 100644 --- a/src/encoding/json/encode_test.go +++ b/src/encoding/json/encode_test.go @@ -405,6 +405,19 @@ func TestAnonymousFields(t *testing.T) { return S{s1{1, 2, s2{3, 4}}, 6} }, want: `{"MyInt1":1,"MyInt2":3}`, + }, { + // If an anonymous struct pointer field is nil, we should ignore + // the embedded fields behind it. Not properly doing so may + // result in the wrong output or reflect panics. + label: "EmbeddedFieldBehindNilPointer", + makeInput: func() interface{} { + type ( + S2 struct{ Field string } + S struct{ *S2 } + ) + return S{} + }, + want: `{}`, }} for _, tt := range tests {