You've already forked json-iterator
mirror of
https://github.com/json-iterator/go.git
synced 2025-06-15 22:50:24 +02:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
6ed27152e0 | |||
3c298d8a76 | |||
9f6e5962a9 | |||
c463aa12c4 | |||
b5d2607a6d | |||
48cc4d965a | |||
c59c42fda0 | |||
8324374402 | |||
2017f3866b | |||
ddc5af4512 | |||
2f7e5c8dd7 |
@ -76,5 +76,7 @@ Contributors
|
|||||||
* [thockin](https://github.com/thockin)
|
* [thockin](https://github.com/thockin)
|
||||||
* [mattn](https://github.com/mattn)
|
* [mattn](https://github.com/mattn)
|
||||||
* [cch123](https://github.com/cch123)
|
* [cch123](https://github.com/cch123)
|
||||||
|
* [Oleg Shaldybin](https://github.com/olegshaldybin)
|
||||||
|
* [Jason Toffaletti](https://github.com/toffaletti)
|
||||||
|
|
||||||
Report issue or pull request, or email taowen@gmail.com, or [](https://gitter.im/json-iterator/Lobby)
|
Report issue or pull request, or email taowen@gmail.com, or [](https://gitter.im/json-iterator/Lobby)
|
||||||
|
@ -32,12 +32,10 @@ type intCodec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *intCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *intCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*int)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*int)(ptr)) = iter.ReadInt()
|
*((*int)(ptr)) = iter.ReadInt()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *intCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *intCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteInt(*((*int)(ptr)))
|
stream.WriteInt(*((*int)(ptr)))
|
||||||
@ -55,12 +53,10 @@ type uintptrCodec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uintptrCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *uintptrCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uintptr)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*uintptr)(ptr)) = uintptr(iter.ReadUint64())
|
*((*uintptr)(ptr)) = uintptr(iter.ReadUint64())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *uintptrCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *uintptrCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteUint64(uint64(*((*uintptr)(ptr))))
|
stream.WriteUint64(uint64(*((*uintptr)(ptr))))
|
||||||
@ -78,12 +74,10 @@ type int8Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uint8)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*int8)(ptr)) = iter.ReadInt8()
|
*((*int8)(ptr)) = iter.ReadInt8()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteInt8(*((*int8)(ptr)))
|
stream.WriteInt8(*((*int8)(ptr)))
|
||||||
@ -101,12 +95,10 @@ type int16Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*int16)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*int16)(ptr)) = iter.ReadInt16()
|
*((*int16)(ptr)) = iter.ReadInt16()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteInt16(*((*int16)(ptr)))
|
stream.WriteInt16(*((*int16)(ptr)))
|
||||||
@ -124,12 +116,10 @@ type int32Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*int32)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*int32)(ptr)) = iter.ReadInt32()
|
*((*int32)(ptr)) = iter.ReadInt32()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteInt32(*((*int32)(ptr)))
|
stream.WriteInt32(*((*int32)(ptr)))
|
||||||
@ -147,12 +137,10 @@ type int64Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*int64)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*int64)(ptr)) = iter.ReadInt64()
|
*((*int64)(ptr)) = iter.ReadInt64()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteInt64(*((*int64)(ptr)))
|
stream.WriteInt64(*((*int64)(ptr)))
|
||||||
@ -170,11 +158,10 @@ type uintCodec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uintCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *uintCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uint)(ptr)) = 0
|
*((*uint)(ptr)) = iter.ReadUint()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*((*uint)(ptr)) = iter.ReadUint()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uintCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *uintCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
@ -193,12 +180,10 @@ type uint8Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uint8)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*uint8)(ptr)) = iter.ReadUint8()
|
*((*uint8)(ptr)) = iter.ReadUint8()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteUint8(*((*uint8)(ptr)))
|
stream.WriteUint8(*((*uint8)(ptr)))
|
||||||
@ -216,12 +201,10 @@ type uint16Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uint16)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*uint16)(ptr)) = iter.ReadUint16()
|
*((*uint16)(ptr)) = iter.ReadUint16()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteUint16(*((*uint16)(ptr)))
|
stream.WriteUint16(*((*uint16)(ptr)))
|
||||||
@ -239,12 +222,10 @@ type uint32Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uint32)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*uint32)(ptr)) = iter.ReadUint32()
|
*((*uint32)(ptr)) = iter.ReadUint32()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteUint32(*((*uint32)(ptr)))
|
stream.WriteUint32(*((*uint32)(ptr)))
|
||||||
@ -262,12 +243,10 @@ type uint64Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*uint64)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*uint64)(ptr)) = iter.ReadUint64()
|
*((*uint64)(ptr)) = iter.ReadUint64()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteUint64(*((*uint64)(ptr)))
|
stream.WriteUint64(*((*uint64)(ptr)))
|
||||||
@ -285,12 +264,10 @@ type float32Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*float32)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*float32)(ptr)) = iter.ReadFloat32()
|
*((*float32)(ptr)) = iter.ReadFloat32()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteFloat32(*((*float32)(ptr)))
|
stream.WriteFloat32(*((*float32)(ptr)))
|
||||||
@ -308,12 +285,10 @@ type float64Codec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
if iter.ReadNil() {
|
if !iter.ReadNil() {
|
||||||
*((*float64)(ptr)) = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*((*float64)(ptr)) = iter.ReadFloat64()
|
*((*float64)(ptr)) = iter.ReadFloat64()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteFloat64(*((*float64)(ptr)))
|
stream.WriteFloat64(*((*float64)(ptr)))
|
||||||
@ -352,13 +327,39 @@ type emptyInterfaceCodec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (codec *emptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (codec *emptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
|
existing := *((*interface{})(ptr))
|
||||||
|
|
||||||
|
// Checking for both typed and untyped nil pointers.
|
||||||
|
if existing != nil &&
|
||||||
|
reflect.TypeOf(existing).Kind() == reflect.Ptr &&
|
||||||
|
!reflect.ValueOf(existing).IsNil() {
|
||||||
|
|
||||||
|
var ptrToExisting interface{}
|
||||||
|
for {
|
||||||
|
elem := reflect.ValueOf(existing).Elem()
|
||||||
|
if elem.Kind() != reflect.Ptr || elem.IsNil() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ptrToExisting = existing
|
||||||
|
existing = elem.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
if iter.ReadNil() {
|
if iter.ReadNil() {
|
||||||
|
if ptrToExisting != nil {
|
||||||
|
nilPtr := reflect.Zero(reflect.TypeOf(ptrToExisting).Elem())
|
||||||
|
reflect.ValueOf(ptrToExisting).Elem().Set(nilPtr)
|
||||||
|
} else {
|
||||||
*((*interface{})(ptr)) = nil
|
*((*interface{})(ptr)) = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iter.ReadVal(existing)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
existing := *((*interface{})(ptr))
|
|
||||||
if existing != nil && reflect.TypeOf(existing).Kind() == reflect.Ptr {
|
if iter.ReadNil() {
|
||||||
iter.ReadVal(existing)
|
*((*interface{})(ptr)) = nil
|
||||||
} else {
|
} else {
|
||||||
*((*interface{})(ptr)) = iter.Read()
|
*((*interface{})(ptr)) = iter.Read()
|
||||||
}
|
}
|
||||||
@ -391,15 +392,20 @@ func (codec *nonEmptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator)
|
|||||||
e.typ = nonEmptyInterface.itab.typ
|
e.typ = nonEmptyInterface.itab.typ
|
||||||
e.word = nonEmptyInterface.word
|
e.word = nonEmptyInterface.word
|
||||||
iter.ReadVal(&i)
|
iter.ReadVal(&i)
|
||||||
|
if e.word == nil {
|
||||||
|
nonEmptyInterface.itab = nil
|
||||||
|
}
|
||||||
nonEmptyInterface.word = e.word
|
nonEmptyInterface.word = e.word
|
||||||
}
|
}
|
||||||
|
|
||||||
func (codec *nonEmptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *nonEmptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
nonEmptyInterface := (*nonEmptyInterface)(ptr)
|
nonEmptyInterface := (*nonEmptyInterface)(ptr)
|
||||||
var i interface{}
|
var i interface{}
|
||||||
|
if nonEmptyInterface.itab != nil {
|
||||||
e := (*emptyInterface)(unsafe.Pointer(&i))
|
e := (*emptyInterface)(unsafe.Pointer(&i))
|
||||||
e.typ = nonEmptyInterface.itab.typ
|
e.typ = nonEmptyInterface.itab.typ
|
||||||
e.word = nonEmptyInterface.word
|
e.word = nonEmptyInterface.word
|
||||||
|
}
|
||||||
stream.WriteVal(i)
|
stream.WriteVal(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,7 +666,11 @@ func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|||||||
templateInterface := encoder.templateInterface
|
templateInterface := encoder.templateInterface
|
||||||
templateInterface.word = ptr
|
templateInterface.word = ptr
|
||||||
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||||
marshaler := (*realInterface).(json.Marshaler)
|
marshaler, ok := (*realInterface).(json.Marshaler)
|
||||||
|
if !ok {
|
||||||
|
stream.WriteVal(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
bytes, err := marshaler.MarshalJSON()
|
bytes, err := marshaler.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -92,22 +92,22 @@ func Test_bool_can_be_null(t *testing.T) {
|
|||||||
obj := TestData{}
|
obj := TestData{}
|
||||||
data1 := []byte(`{"field": true}`)
|
data1 := []byte(`{"field": true}`)
|
||||||
err := Unmarshal(data1, &obj)
|
err := Unmarshal(data1, &obj)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(true, obj.Field)
|
should.Equal(true, obj.Field)
|
||||||
|
|
||||||
data2 := []byte(`{"field": null}`)
|
data2 := []byte(`{"field": null}`)
|
||||||
err = Unmarshal(data2, &obj)
|
err = Unmarshal(data2, &obj)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
// Same behavior as stdlib, not touching the existing value.
|
// Same behavior as stdlib, not touching the existing value.
|
||||||
should.Equal(true, obj.Field)
|
should.Equal(true, obj.Field)
|
||||||
|
|
||||||
// Checking stdlib behavior as well
|
// Checking stdlib behavior as well
|
||||||
obj2 := TestData{}
|
obj2 := TestData{}
|
||||||
err = json.Unmarshal(data1, &obj2)
|
err = json.Unmarshal(data1, &obj2)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(true, obj2.Field)
|
should.Equal(true, obj2.Field)
|
||||||
|
|
||||||
err = json.Unmarshal(data2, &obj2)
|
err = json.Unmarshal(data2, &obj2)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(true, obj2.Field)
|
should.Equal(true, obj2.Field)
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,11 @@ func Test_custom_marshaler_on_enum(t *testing.T) {
|
|||||||
w := Wrapper{Payload: MyEnumB}
|
w := Wrapper{Payload: MyEnumB}
|
||||||
|
|
||||||
jb, err := Marshal(w)
|
jb, err := Marshal(w)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(`{"Payload":"foo-1"}`, string(jb))
|
should.Equal(`{"Payload":"foo-1"}`, string(jb))
|
||||||
|
|
||||||
var w2 Wrapper2
|
var w2 Wrapper2
|
||||||
err = Unmarshal(jb, &w2)
|
err = Unmarshal(jb, &w2)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(MyEnumB, w2.Payload)
|
should.Equal(MyEnumB, w2.Payload)
|
||||||
}
|
}
|
||||||
|
@ -329,13 +329,13 @@ func Test_nil_out_null_interface(t *testing.T) {
|
|||||||
data1 := []byte(`{"field": true}`)
|
data1 := []byte(`{"field": true}`)
|
||||||
|
|
||||||
err := Unmarshal(data1, &obj)
|
err := Unmarshal(data1, &obj)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(true, *(obj.Field.(*bool)))
|
should.Equal(true, *(obj.Field.(*bool)))
|
||||||
|
|
||||||
data2 := []byte(`{"field": null}`)
|
data2 := []byte(`{"field": null}`)
|
||||||
|
|
||||||
err = Unmarshal(data2, &obj)
|
err = Unmarshal(data2, &obj)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(nil, obj.Field)
|
should.Equal(nil, obj.Field)
|
||||||
|
|
||||||
// Checking stdlib behavior matches.
|
// Checking stdlib behavior matches.
|
||||||
@ -344,11 +344,11 @@ func Test_nil_out_null_interface(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(data1, &obj2)
|
err = json.Unmarshal(data1, &obj2)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(true, *(obj2.Field.(*bool)))
|
should.Equal(true, *(obj2.Field.(*bool)))
|
||||||
|
|
||||||
err = json.Unmarshal(data2, &obj2)
|
err = json.Unmarshal(data2, &obj2)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(nil, obj2.Field)
|
should.Equal(nil, obj2.Field)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,10 +363,198 @@ func Test_omitempty_nil_interface(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
js, err := json.Marshal(obj)
|
js, err := json.Marshal(obj)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal("{}", string(js))
|
should.Equal("{}", string(js))
|
||||||
|
|
||||||
str, err := MarshalToString(obj)
|
str, err := MarshalToString(obj)
|
||||||
should.Equal(nil, err)
|
should.NoError(err)
|
||||||
should.Equal(string(js), str)
|
should.Equal(string(js), str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_omitempty_nil_nonempty_interface(t *testing.T) {
|
||||||
|
type TestData struct {
|
||||||
|
Field MyInterface `json:"field,omitempty"`
|
||||||
|
}
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
obj := TestData{
|
||||||
|
Field: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
js, err := json.Marshal(obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal("{}", string(js))
|
||||||
|
|
||||||
|
str, err := MarshalToString(obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(string(js), str)
|
||||||
|
|
||||||
|
obj.Field = MyString("hello")
|
||||||
|
err = UnmarshalFromString(`{"field":null}`, &obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(nil, obj.Field)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_marshal_nil_marshaler_interface(t *testing.T) {
|
||||||
|
type TestData struct {
|
||||||
|
Field json.Marshaler `json:"field"`
|
||||||
|
}
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
obj := TestData{
|
||||||
|
Field: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
js, err := json.Marshal(obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(`{"field":null}`, string(js))
|
||||||
|
|
||||||
|
str, err := MarshalToString(obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(string(js), str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_marshal_nil_nonempty_interface(t *testing.T) {
|
||||||
|
type TestData struct {
|
||||||
|
Field MyInterface `json:"field"`
|
||||||
|
}
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
obj := TestData{
|
||||||
|
Field: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
js, err := json.Marshal(obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(`{"field":null}`, string(js))
|
||||||
|
|
||||||
|
str, err := MarshalToString(obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(string(js), str)
|
||||||
|
|
||||||
|
obj.Field = MyString("hello")
|
||||||
|
err = Unmarshal(js, &obj)
|
||||||
|
should.NoError(err)
|
||||||
|
should.Equal(nil, obj.Field)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_overwrite_interface_ptr_value_with_nil(t *testing.T) {
|
||||||
|
type Wrapper struct {
|
||||||
|
Payload interface{} `json:"payload,omitempty"`
|
||||||
|
}
|
||||||
|
type Payload struct {
|
||||||
|
Value int `json:"val,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
payload := &Payload{}
|
||||||
|
wrapper := &Wrapper{
|
||||||
|
Payload: &payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(&payload, wrapper.Payload)
|
||||||
|
should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)
|
||||||
|
|
||||||
|
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(&payload, wrapper.Payload)
|
||||||
|
should.Equal((*Payload)(nil), payload)
|
||||||
|
|
||||||
|
payload = &Payload{}
|
||||||
|
wrapper = &Wrapper{
|
||||||
|
Payload: &payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(&payload, wrapper.Payload)
|
||||||
|
should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)
|
||||||
|
|
||||||
|
err = Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(&payload, wrapper.Payload)
|
||||||
|
should.Equal((*Payload)(nil), payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_overwrite_interface_value_with_nil(t *testing.T) {
|
||||||
|
type Wrapper struct {
|
||||||
|
Payload interface{} `json:"payload,omitempty"`
|
||||||
|
}
|
||||||
|
type Payload struct {
|
||||||
|
Value int `json:"val,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
payload := &Payload{}
|
||||||
|
wrapper := &Wrapper{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
|
||||||
|
|
||||||
|
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(nil, wrapper.Payload)
|
||||||
|
should.Equal(42, payload.Value)
|
||||||
|
|
||||||
|
payload = &Payload{}
|
||||||
|
wrapper = &Wrapper{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
|
||||||
|
|
||||||
|
err = Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(nil, wrapper.Payload)
|
||||||
|
should.Equal(42, payload.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_unmarshal_into_nil(t *testing.T) {
|
||||||
|
type Payload struct {
|
||||||
|
Value int `json:"val,omitempty"`
|
||||||
|
}
|
||||||
|
type Wrapper struct {
|
||||||
|
Payload interface{} `json:"payload,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
var payload *Payload
|
||||||
|
wrapper := &Wrapper{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
|
should.Nil(err)
|
||||||
|
should.NotNil(wrapper.Payload)
|
||||||
|
should.Nil(payload)
|
||||||
|
|
||||||
|
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
|
should.Nil(err)
|
||||||
|
should.Nil(wrapper.Payload)
|
||||||
|
should.Nil(payload)
|
||||||
|
|
||||||
|
payload = nil
|
||||||
|
wrapper = &Wrapper{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
|
should.Nil(err)
|
||||||
|
should.NotNil(wrapper.Payload)
|
||||||
|
should.Nil(payload)
|
||||||
|
|
||||||
|
err = Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
|
should.Nil(err)
|
||||||
|
should.Nil(wrapper.Payload)
|
||||||
|
should.Nil(payload)
|
||||||
|
}
|
||||||
|
@ -3,9 +3,10 @@ package jsoniter
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_null(t *testing.T) {
|
func Test_read_null(t *testing.T) {
|
||||||
@ -135,3 +136,33 @@ func Test_encode_nil_array(t *testing.T) {
|
|||||||
should.Nil(err)
|
should.Nil(err)
|
||||||
should.Equal("null", string(output))
|
should.Equal("null", string(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_decode_nil_num(t *testing.T) {
|
||||||
|
type TestData struct {
|
||||||
|
Field int `json:"field"`
|
||||||
|
}
|
||||||
|
should := require.New(t)
|
||||||
|
|
||||||
|
data1 := []byte(`{"field": 42}`)
|
||||||
|
data2 := []byte(`{"field": null}`)
|
||||||
|
|
||||||
|
// Checking stdlib behavior as well
|
||||||
|
obj2 := TestData{}
|
||||||
|
err := json.Unmarshal(data1, &obj2)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(42, obj2.Field)
|
||||||
|
|
||||||
|
err = json.Unmarshal(data2, &obj2)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(42, obj2.Field)
|
||||||
|
|
||||||
|
obj := TestData{}
|
||||||
|
|
||||||
|
err = Unmarshal(data1, &obj)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(42, obj.Field)
|
||||||
|
|
||||||
|
err = Unmarshal(data2, &obj)
|
||||||
|
should.Equal(nil, err)
|
||||||
|
should.Equal(42, obj.Field)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user