diff --git a/src/pkg/encoding/json/encode.go b/src/pkg/encoding/json/encode.go index 69deaf2a40d..ff8e80c091e 100644 --- a/src/pkg/encoding/json/encode.go +++ b/src/pkg/encoding/json/encode.go @@ -339,13 +339,10 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) { e.WriteString("null") break } - // Slices can be marshalled as nil, but otherwise are handled - // as arrays. - fallthrough - case reflect.Array: - if v.Type() == byteSliceType { + if v.Type().Elem().Kind() == reflect.Uint8 { + // Byte slices get special treatment; arrays don't. + s := v.Bytes() e.WriteByte('"') - s := v.Interface().([]byte) if len(s) < 1024 { // for small buffers, using Encode directly is much faster. dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) @@ -361,6 +358,10 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) { e.WriteByte('"') break } + // Slices can be marshalled as nil, but otherwise are handled + // as arrays. + fallthrough + case reflect.Array: e.WriteByte('[') n := v.Len() for i := 0; i < n; i++ { diff --git a/src/pkg/encoding/json/encode_test.go b/src/pkg/encoding/json/encode_test.go index 92f266aba63..9366589f252 100644 --- a/src/pkg/encoding/json/encode_test.go +++ b/src/pkg/encoding/json/encode_test.go @@ -82,3 +82,28 @@ func TestStringTag(t *testing.T) { t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2) } } + +// byte slices are special even if they're renamed types. +type renamedByte byte +type renamedByteSlice []byte +type renamedRenamedByteSlice []renamedByte + +func TestEncodeRenamedByteSlice(t *testing.T) { + s := renamedByteSlice("abc") + result, err := Marshal(s) + if err != nil { + t.Fatal(err) + } + expect := `"YWJj"` + if string(result) != expect { + t.Errorf(" got %s want %s", result, expect) + } + r := renamedRenamedByteSlice("abc") + result, err = Marshal(r) + if err != nil { + t.Fatal(err) + } + if string(result) != expect { + t.Errorf(" got %s want %s", result, expect) + } +}