1
0
mirror of https://github.com/json-iterator/go.git synced 2025-02-01 19:14:29 +02:00

#31 support json.RawMessage

This commit is contained in:
Tao Wen 2017-06-02 10:50:23 +08:00
parent ad3a7fde32
commit fe9fa8900e
4 changed files with 46 additions and 6 deletions

View File

@ -145,6 +145,9 @@ func (iter *Iterator) readNumberAsString() (ret string) {
if iter.Error != nil && iter.Error != io.EOF {
return
}
if len(str) == 0 {
iter.reportError("readNumberAsString", "invalid number")
}
return *(*string)(unsafe.Pointer(&str))
}

View File

@ -73,6 +73,7 @@ var typeEncoders map[string]Encoder
var fieldEncoders map[string]Encoder
var extensions []ExtensionFunc
var jsonNumberType reflect.Type
var jsonRawMessageType reflect.Type
var anyType reflect.Type
var marshalerType reflect.Type
var unmarshalerType reflect.Type
@ -86,6 +87,7 @@ func init() {
atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{}))
atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{}))
jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
anyType = reflect.TypeOf((*Any)(nil)).Elem()
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
@ -335,16 +337,19 @@ func decoderOfType(typ reflect.Type) (Decoder, error) {
}
func createDecoderOfType(typ reflect.Type) (Decoder, error) {
if typ.ConvertibleTo(jsonRawMessageType) {
return &jsonRawMessageCodec{}, nil
}
if typ.ConvertibleTo(jsonNumberType) {
return &jsonNumberCodec{}, nil
}
if typ.ConvertibleTo(anyType) {
return &anyCodec{}, nil
}
if typ.ConvertibleTo(unmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
return &optionalDecoder{typ, &unmarshalerDecoder{extractInterface(templateInterface)}}, nil
}
if typ.ConvertibleTo(anyType) {
return &anyCodec{}, nil
}
switch typ.Kind() {
case reflect.String:
return &stringCodec{}, nil
@ -419,16 +424,19 @@ func encoderOfType(typ reflect.Type) (Encoder, error) {
}
func createEncoderOfType(typ reflect.Type) (Encoder, error) {
if typ.ConvertibleTo(jsonRawMessageType) {
return &jsonRawMessageCodec{}, nil
}
if typ.ConvertibleTo(jsonNumberType) {
return &jsonNumberCodec{}, nil
}
if typ.ConvertibleTo(anyType) {
return &anyCodec{}, nil
}
if typ.ConvertibleTo(marshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
return &marshalerEncoder{extractInterface(templateInterface)}, nil
}
if typ.ConvertibleTo(anyType) {
return &anyCodec{}, nil
}
kind := typ.Kind()
switch kind {
case reflect.String:

View File

@ -360,6 +360,25 @@ func (encoder *jsonNumberCodec) isEmpty(ptr unsafe.Pointer) bool {
return len(*((*json.Number)(ptr))) == 0
}
type jsonRawMessageCodec struct {
}
func (codec *jsonRawMessageCodec) decode(ptr unsafe.Pointer, iter *Iterator) {
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsonRawMessageCodec) encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
}
func (encoder *jsonRawMessageCodec) encodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(json.RawMessage)))
}
func (encoder *jsonRawMessageCodec) isEmpty(ptr unsafe.Pointer) bool {
return len(*((*json.RawMessage)(ptr))) == 0
}
type stringNumberDecoder struct {
elemDecoder Decoder
}

View File

@ -253,6 +253,16 @@ func Test_write_array_of_interface_in_struct(t *testing.T) {
should.Equal(`{"Field":[1,2],"Field2":""}`, str)
}
func Test_json_RawMessage(t *testing.T) {
should := require.New(t)
var data json.RawMessage
should.Nil(Unmarshal([]byte(`[1,2,3]`), &data))
should.Equal(`[1,2,3]`, string(data))
str, err := MarshalToString(data)
should.Nil(err)
should.Equal(`[1,2,3]`, str)
}
func Benchmark_jsoniter_array(b *testing.B) {
b.ReportAllocs()
input := []byte(`[1,2,3,4,5,6,7,8,9]`)