diff --git a/feature_reflect.go b/feature_reflect.go index f02994b..f4dfcbf 100644 --- a/feature_reflect.go +++ b/feature_reflect.go @@ -72,6 +72,7 @@ var fieldDecoders map[string]Decoder var typeEncoders map[string]Encoder var fieldEncoders map[string]Encoder var extensions []ExtensionFunc +var jsonNumberType reflect.Type var anyType reflect.Type var marshalerType reflect.Type var unmarshalerType reflect.Type @@ -84,6 +85,7 @@ func init() { extensions = []ExtensionFunc{} atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{})) atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{})) + jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem() anyType = reflect.TypeOf((*Any)(nil)).Elem() marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem() unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() @@ -333,6 +335,9 @@ func decoderOfType(typ reflect.Type) (Decoder, error) { } func createDecoderOfType(typ reflect.Type) (Decoder, error) { + if typ.ConvertibleTo(jsonNumberType) { + return &jsonNumberCodec{}, nil + } if typ.ConvertibleTo(anyType) { return &anyCodec{}, nil } @@ -414,6 +419,9 @@ func encoderOfType(typ reflect.Type) (Encoder, error) { } func createEncoderOfType(typ reflect.Type) (Encoder, error) { + if typ.ConvertibleTo(jsonNumberType) { + return &jsonNumberCodec{}, nil + } if typ.ConvertibleTo(anyType) { return &anyCodec{}, nil } diff --git a/feature_reflect_native.go b/feature_reflect_native.go index 3e4e51d..f2b2f7c 100644 --- a/feature_reflect_native.go +++ b/feature_reflect_native.go @@ -341,6 +341,25 @@ func (encoder *anyCodec) isEmpty(ptr unsafe.Pointer) bool { return (*((*Any)(ptr))).Size() == 0 } +type jsonNumberCodec struct { +} + +func (codec *jsonNumberCodec) decode(ptr unsafe.Pointer, iter *Iterator) { + *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) +} + +func (codec *jsonNumberCodec) encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*json.Number)(ptr)))) +} + +func (encoder *jsonNumberCodec) encodeInterface(val interface{}, stream *Stream) { + stream.WriteRaw(string(val.(json.Number))) +} + +func (encoder *jsonNumberCodec) isEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.Number)(ptr))) == 0 +} + type stringNumberDecoder struct { elemDecoder Decoder } diff --git a/jsoniter_int_test.go b/jsoniter_int_test.go index 5bea263..f91cdef 100644 --- a/jsoniter_int_test.go +++ b/jsoniter_int_test.go @@ -421,6 +421,17 @@ func Test_write_val_int_ptr(t *testing.T) { should.Equal("1001", buf.String()) } +func Test_json_number(t *testing.T) { + should := require.New(t) + var arr []json.Number + err := Unmarshal([]byte(`[1]`), &arr) + should.Nil(err) + should.Equal(json.Number("1"), arr[0]) + str, err := MarshalToString(arr) + should.Nil(err) + should.Equal(`[1]`, str) +} + func Benchmark_jsoniter_encode_int(b *testing.B) { stream := NewStream(ioutil.Discard, 64) for n := 0; n < b.N; n++ {