1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-20 11:28:49 +02:00

#139 unmarshal non base64 into []byte

This commit is contained in:
Tao Wen 2017-07-19 12:04:22 +08:00
parent 12cd299fa8
commit c15b4d116c
4 changed files with 42 additions and 21 deletions

View File

@ -281,7 +281,11 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
return &jsonNumberCodec{}, nil return &jsonNumberCodec{}, nil
} }
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 { if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return &base64Codec{}, nil sliceDecoder, err := prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
if err != nil {
return nil, err
}
return &base64Codec{sliceDecoder: sliceDecoder}, nil
} }
if typ.Implements(unmarshalerType) { if typ.Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface() templateInterface := reflect.New(typ).Elem().Interface()
@ -440,7 +444,7 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
return &jsonNumberCodec{}, nil return &jsonNumberCodec{}, nil
} }
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 { if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return &base64Codec{typ}, nil return &base64Codec{}, nil
} }
if typ.Implements(marshalerType) { if typ.Implements(marshalerType) {
checkIsEmpty, err := createCheckIsEmpty(typ) checkIsEmpty, err := createCheckIsEmpty(typ)

View File

@ -4,7 +4,6 @@ import (
"encoding" "encoding"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"reflect"
"unsafe" "unsafe"
) )
@ -425,7 +424,7 @@ func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
} }
type base64Codec struct { type base64Codec struct {
actualType reflect.Type sliceDecoder ValDecoder
} }
func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
@ -436,21 +435,28 @@ func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
ptrSlice.Data = nil ptrSlice.Data = nil
return return
} }
encoding := base64.StdEncoding switch iter.WhatIsNext() {
src := iter.SkipAndReturnBytes() case String:
src = src[1 : len(src)-1] encoding := base64.StdEncoding
decodedLen := encoding.DecodedLen(len(src)) src := iter.SkipAndReturnBytes()
dst := make([]byte, decodedLen) src = src[1 : len(src)-1]
len, err := encoding.Decode(dst, src) decodedLen := encoding.DecodedLen(len(src))
if err != nil { dst := make([]byte, decodedLen)
iter.ReportError("decode base64", err.Error()) len, err := encoding.Decode(dst, src)
} else { if err != nil {
dst = dst[:len] iter.ReportError("decode base64", err.Error())
dstSlice := (*sliceHeader)(unsafe.Pointer(&dst)) } else {
ptrSlice := (*sliceHeader)(ptr) dst = dst[:len]
ptrSlice.Data = dstSlice.Data dstSlice := (*sliceHeader)(unsafe.Pointer(&dst))
ptrSlice.Cap = dstSlice.Cap ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Len = dstSlice.Len ptrSlice.Data = dstSlice.Data
ptrSlice.Cap = dstSlice.Cap
ptrSlice.Len = dstSlice.Len
}
case Array:
codec.sliceDecoder.Decode(ptr, iter)
default:
iter.ReportError("base64Codec", "invalid input")
} }
} }

View File

@ -156,7 +156,7 @@ func Test_encode_byte_array(t *testing.T) {
should.Equal(`"AQID"`, string(bytes)) should.Equal(`"AQID"`, string(bytes))
} }
func Test_decode_byte_array(t *testing.T) { func Test_decode_byte_array_from_base64(t *testing.T) {
should := require.New(t) should := require.New(t)
data := []byte{} data := []byte{}
err := json.Unmarshal([]byte(`"AQID"`), &data) err := json.Unmarshal([]byte(`"AQID"`), &data)
@ -167,6 +167,17 @@ func Test_decode_byte_array(t *testing.T) {
should.Equal([]byte{1, 2, 3}, data) should.Equal([]byte{1, 2, 3}, data)
} }
func Test_decode_byte_array_from_array(t *testing.T) {
should := require.New(t)
data := []byte{}
err := json.Unmarshal([]byte(`[1,2,3]`), &data)
should.Nil(err)
should.Equal([]byte{1, 2, 3}, data)
err = Unmarshal([]byte(`[1,2,3]`), &data)
should.Nil(err)
should.Equal([]byte{1, 2, 3}, data)
}
func Test_decode_slice(t *testing.T) { func Test_decode_slice(t *testing.T) {
should := require.New(t) should := require.New(t)
slice := make([]string, 0, 5) slice := make([]string, 0, 5)

View File

@ -122,7 +122,7 @@ func init() {
/* /*
200000 8886 ns/op 4336 B/op 6 allocs/op 200000 8886 ns/op 4336 B/op 6 allocs/op
50000 34244 ns/op 6744 B/op 14 allocs/op 50000 34244 ns/op 6744 B/op 14 allocs/op
*/ */
func Benchmark_jsoniter_large_file(b *testing.B) { func Benchmark_jsoniter_large_file(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {