Browse Source

#56 nil map or array should be null not [] or {}

Tao Wen 8 years ago
parent
commit
788918b85d
6 changed files with 64 additions and 6 deletions
  1. 12 3
      feature_reflect.go
  2. 4 0
      feature_reflect_array.go
  3. 1 1
      jsoniter_array_test.go
  4. 0 2
      jsoniter_map_test.go
  5. 37 0
      jsoniter_null_test.go
  6. 10 0
      jsoniter_string_test.go

+ 12 - 3
feature_reflect.go

@@ -34,6 +34,10 @@ type Encoder interface {
 
 func writeToStream(val interface{}, stream *Stream, encoder Encoder) {
 	e := (*emptyInterface)(unsafe.Pointer(&val))
+	if e.word == nil {
+		stream.WriteNil()
+		return
+	}
 	if reflect.TypeOf(val).Kind() == reflect.Ptr {
 		encoder.encode(unsafe.Pointer(&e.word), stream)
 	} else {
@@ -512,11 +516,15 @@ func decoderOfOptional(typ reflect.Type) (Decoder, error) {
 
 func encoderOfOptional(typ reflect.Type) (Encoder, error) {
 	elemType := typ.Elem()
-	decoder, err := encoderOfType(elemType)
+	elemEncoder, err := encoderOfType(elemType)
 	if err != nil {
 		return nil, err
 	}
-	return &optionalEncoder{decoder}, nil
+	encoder := &optionalEncoder{elemEncoder}
+	if elemType.Kind() == reflect.Map {
+		encoder = &optionalEncoder{encoder}
+	}
+	return encoder, nil
 }
 
 func decoderOfMap(typ reflect.Type) (Decoder, error) {
@@ -539,5 +547,6 @@ func encoderOfMap(typ reflect.Type) (Encoder, error) {
 		return nil, err
 	}
 	mapInterface := reflect.New(typ).Elem().Interface()
-	return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
+	encoderForMap := &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
+	return encoderForMap, nil
 }

+ 4 - 0
feature_reflect_array.go

@@ -34,6 +34,10 @@ type sliceEncoder struct {
 
 func (encoder *sliceEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
 	slice := (*sliceHeader)(ptr)
+	if slice.Data == nil {
+		stream.WriteNil()
+		return
+	}
 	if slice.Len == 0 {
 		stream.WriteEmptyArray()
 		return

+ 1 - 1
jsoniter_array_test.go

@@ -228,7 +228,7 @@ func Test_write_array(t *testing.T) {
 func Test_write_val_array(t *testing.T) {
 	should := require.New(t)
 	val := []int{1, 2, 3}
-	str, err := MarshalToString(val)
+	str, err := MarshalToString(&val)
 	should.Nil(err)
 	should.Equal("[1,2,3]", str)
 }

+ 0 - 2
jsoniter_map_test.go

@@ -103,8 +103,6 @@ func Test_decode_TextMarshaler_key_map(t *testing.T) {
 	should.Equal(`{"1":"2"}`, str)
 }
 
-
-
 func Test_map_key_with_escaped_char(t *testing.T) {
 	type Ttest struct {
 		Map map[string]string

+ 37 - 0
jsoniter_null_test.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"github.com/json-iterator/go/require"
 	"testing"
+	"encoding/json"
 )
 
 func Test_read_null(t *testing.T) {
@@ -87,3 +88,39 @@ func Test_decode_null_skip(t *testing.T) {
 		t.FailNow()
 	}
 }
+
+func Test_encode_nil_map(t *testing.T) {
+	should := require.New(t)
+	type Ttest map[string]string
+	var obj1 Ttest
+	output, err := json.Marshal(obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+	output, err = json.Marshal(&obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+	output, err = Marshal(obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+	output, err = Marshal(&obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+}
+
+func Test_encode_nil_array(t *testing.T) {
+	should := require.New(t)
+	type Ttest []string
+	var obj1 Ttest
+	output, err := json.Marshal(obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+	output, err = json.Marshal(&obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+	output, err = Marshal(obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+	output, err = Marshal(&obj1)
+	should.Nil(err)
+	should.Equal("null", string(output))
+}

+ 10 - 0
jsoniter_string_test.go

@@ -112,6 +112,16 @@ func Test_decode_slash(t *testing.T) {
 	should.NotNil(UnmarshalFromString("\\", &obj))
 }
 
+//func Test_html_escape(t *testing.T) {
+//	should := require.New(t)
+//	output, err := json.Marshal(`>`)
+//	should.Nil(err)
+//	should.Equal(`"\u003e"`, string(output))
+//	output, err = Marshal(`>`)
+//	should.Nil(err)
+//	should.Equal(`"\u003e"`, string(output))
+//}
+
 func Benchmark_jsoniter_unicode(b *testing.B) {
 	for n := 0; n < b.N; n++ {
 		iter := ParseString(`"\ud83d\udc4a"`)