mirror of
https://github.com/json-iterator/go.git
synced 2025-05-13 21:36:29 +02:00
Allow null booleans
Make sure we do the same thing as stdlib with null booleans by not touching the original value and discarding the null. Another somewhat related change is nulling out null interface values in the original structure. This also matches stdlib behavior.
This commit is contained in:
parent
0fdf883ac0
commit
18a241d40b
@ -331,7 +331,9 @@ type boolCodec struct {
|
||||
}
|
||||
|
||||
func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*bool)(ptr)) = iter.ReadBool()
|
||||
if !iter.ReadNil() {
|
||||
*((*bool)(ptr)) = iter.ReadBool()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
@ -350,6 +352,10 @@ type emptyInterfaceCodec struct {
|
||||
}
|
||||
|
||||
func (codec *emptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if iter.ReadNil() {
|
||||
*((*interface{})(ptr)) = nil
|
||||
return
|
||||
}
|
||||
existing := *((*interface{})(ptr))
|
||||
if existing != nil && reflect.TypeOf(existing).Kind() == reflect.Ptr {
|
||||
iter.ReadVal(existing)
|
||||
|
@ -82,3 +82,32 @@ func Test_decode_string_bool(t *testing.T) {
|
||||
err = Unmarshal([]byte(`{"Field":true}`), &obj)
|
||||
should.NotNil(err)
|
||||
}
|
||||
|
||||
func Test_bool_can_be_null(t *testing.T) {
|
||||
type TestData struct {
|
||||
Field bool `json:"field"`
|
||||
}
|
||||
should := require.New(t)
|
||||
|
||||
obj := TestData{}
|
||||
data1 := []byte(`{"field": true}`)
|
||||
err := Unmarshal(data1, &obj)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(true, obj.Field)
|
||||
|
||||
data2 := []byte(`{"field": null}`)
|
||||
err = Unmarshal(data2, &obj)
|
||||
should.Equal(nil, err)
|
||||
// Same behavior as stdlib, not touching the existing value.
|
||||
should.Equal(true, obj.Field)
|
||||
|
||||
// Checking stdlib behavior as well
|
||||
obj2 := TestData{}
|
||||
err = json.Unmarshal(data1, &obj2)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(true, obj2.Field)
|
||||
|
||||
err = json.Unmarshal(data2, &obj2)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(true, obj2.Field)
|
||||
}
|
||||
|
@ -3,9 +3,10 @@ package jsoniter
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_write_array_of_interface(t *testing.T) {
|
||||
@ -313,3 +314,40 @@ func Test_unmarshal_ptr_to_interface(t *testing.T) {
|
||||
should.Nil(err)
|
||||
should.Equal("&{value}", fmt.Sprintf("%v", obj))
|
||||
}
|
||||
|
||||
func Test_nil_out_null_interface(t *testing.T) {
|
||||
type TestData struct {
|
||||
Field interface{} `json:"field"`
|
||||
}
|
||||
should := require.New(t)
|
||||
|
||||
var boolVar bool
|
||||
obj := TestData{
|
||||
Field: &boolVar,
|
||||
}
|
||||
|
||||
data1 := []byte(`{"field": true}`)
|
||||
|
||||
err := Unmarshal(data1, &obj)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(true, *(obj.Field.(*bool)))
|
||||
|
||||
data2 := []byte(`{"field": null}`)
|
||||
|
||||
err = Unmarshal(data2, &obj)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(nil, obj.Field)
|
||||
|
||||
// Checking stdlib behavior matches.
|
||||
obj2 := TestData{
|
||||
Field: &boolVar,
|
||||
}
|
||||
|
||||
err = json.Unmarshal(data1, &obj2)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(true, *(obj2.Field.(*bool)))
|
||||
|
||||
err = json.Unmarshal(data2, &obj2)
|
||||
should.Equal(nil, err)
|
||||
should.Equal(nil, obj2.Field)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user