Просмотр исходного кода

Merge pull request #168 from olegshaldybin/null-booleans

Allow null booleans
Tao Wen 8 лет назад
Родитель
Сommit
f8eb43eda3
3 измененных файлов с 75 добавлено и 2 удалено
  1. 7 1
      feature_reflect_native.go
  2. 29 0
      jsoniter_bool_test.go
  3. 39 1
      jsoniter_interface_test.go

+ 7 - 1
feature_reflect_native.go

@@ -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)

+ 29 - 0
jsoniter_bool_test.go

@@ -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)
+}

+ 39 - 1
jsoniter_interface_test.go

@@ -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)
+}