소스 검색

#68 empty array to object/map

Tao Wen 8 년 전
부모
커밋
85be06b145
4개의 변경된 파일84개의 추가작업 그리고 6개의 파일을 삭제
  1. 28 0
      extra/fuzzy_decoder.go
  2. 14 0
      extra/fuzzy_decoder_test.go
  3. 6 0
      feature_reflect.go
  4. 36 6
      feature_reflect_extension.go

+ 28 - 0
extra/fuzzy_decoder.go

@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"strings"
 	"math"
+	"reflect"
 )
 
 const MaxUint = ^uint(0)
@@ -13,6 +14,7 @@ const MaxInt = int(MaxUint >> 1)
 const MinInt = -MaxInt - 1
 
 func RegisterFuzzyDecoders() {
+	jsoniter.RegisterExtension(&tolerateEmptyArrayExtension{})
 	jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
 	jsoniter.RegisterTypeDecoder("float32", &FuzzyFloat32Decoder{})
 	jsoniter.RegisterTypeDecoder("float64", &FuzzyFloat64Decoder{})
@@ -138,6 +140,32 @@ func RegisterFuzzyDecoders() {
 	}})
 }
 
+type tolerateEmptyArrayExtension struct {
+	jsoniter.DummyExtension
+}
+
+func (extension *tolerateEmptyArrayExtension) DecorateDecoder(typ reflect.Type, decoder jsoniter.ValDecoder) jsoniter.ValDecoder {
+	if typ.Kind() == reflect.Struct || typ.Kind() == reflect.Map {
+		return &tolerateEmptyArrayDecoder{decoder}
+	}
+	return decoder
+}
+
+type tolerateEmptyArrayDecoder struct {
+	valDecoder jsoniter.ValDecoder
+}
+
+func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+	if iter.WhatIsNext() == jsoniter.Array {
+		iter.Skip()
+		newIter := iter.Config().BorrowIterator([]byte("{}"))
+		defer iter.Config().ReturnIterator(newIter)
+		decoder.valDecoder.Decode(ptr, newIter)
+	} else {
+		decoder.valDecoder.Decode(ptr, iter)
+	}
+}
+
 type FuzzyStringDecoder struct {
 }
 

+ 14 - 0
extra/fuzzy_decoder_test.go

@@ -85,3 +85,17 @@ func Test_float_to_float64(t *testing.T) {
 	should.Nil(jsoniter.UnmarshalFromString(`1.23`, &val))
 	should.Equal(float64(1.23), val)
 }
+
+func Test_empty_array_as_map(t *testing.T) {
+	should := require.New(t)
+	var val map[string]interface{}
+	should.Nil(jsoniter.UnmarshalFromString(`[]`, &val))
+	should.Equal(map[string]interface{}{}, val)
+}
+
+func Test_empty_array_as_object(t *testing.T) {
+	should := require.New(t)
+	var val struct{}
+	should.Nil(jsoniter.UnmarshalFromString(`[]`, &val))
+	should.Equal(struct{}{}, val)
+}

+ 6 - 0
feature_reflect.go

@@ -238,6 +238,9 @@ func decoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
 	decoder = &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
 	cfg.addDecoderToCache(cacheKey, decoder)
 	decoder, err := createDecoderOfType(cfg, typ)
+	for _, extension := range extensions {
+		decoder = extension.DecorateDecoder(typ, decoder)
+	}
 	cfg.addDecoderToCache(cacheKey, decoder)
 	return decoder, err
 }
@@ -330,6 +333,9 @@ func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
 	encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
 	cfg.addEncoderToCache(cacheKey, encoder)
 	encoder, err := createEncoderOfType(cfg, typ)
+	for _, extension := range extensions {
+		encoder = extension.DecorateEncoder(typ, encoder)
+	}
 	cfg.addEncoderToCache(cacheKey, encoder)
 	return encoder, err
 }

+ 36 - 6
feature_reflect_extension.go

@@ -29,17 +29,19 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
 }
 
 type Binding struct {
-	Field           *reflect.StructField
-	FromNames       []string
-	ToNames         []string
-	Encoder         ValEncoder
-	Decoder         ValDecoder
+	Field     *reflect.StructField
+	FromNames []string
+	ToNames   []string
+	Encoder   ValEncoder
+	Decoder   ValDecoder
 }
 
 type Extension interface {
 	UpdateStructDescriptor(structDescriptor *StructDescriptor)
 	CreateDecoder(typ reflect.Type) ValDecoder
 	CreateEncoder(typ reflect.Type) ValEncoder
+	DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder
+	DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder
 }
 
 type DummyExtension struct {
@@ -56,9 +58,18 @@ func (extension *DummyExtension) CreateEncoder(typ reflect.Type) ValEncoder {
 	return nil
 }
 
+func (extension *DummyExtension) DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder {
+	return decoder
+}
+
+func (extension *DummyExtension) DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder {
+	return encoder
+}
+
 type funcDecoder struct {
 	fun DecoderFunc
 }
+
 func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
 	decoder.fun(ptr, iter)
 }
@@ -120,6 +131,15 @@ func RegisterExtension(extension Extension) {
 }
 
 func getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
+	decoder := _getTypeDecoderFromExtension(typ)
+	if decoder != nil {
+		for _, extension := range extensions {
+			decoder = extension.DecorateDecoder(typ, decoder)
+		}
+	}
+	return decoder
+}
+func _getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
 	for _, extension := range extensions {
 		decoder := extension.CreateDecoder(typ)
 		if decoder != nil {
@@ -141,6 +161,16 @@ func getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
 }
 
 func getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
+	encoder := _getTypeEncoderFromExtension(typ)
+	if encoder != nil {
+		for _, extension := range extensions {
+			encoder = extension.DecorateEncoder(typ, encoder)
+		}
+	}
+	return encoder
+}
+
+func _getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
 	for _, extension := range extensions {
 		encoder := extension.CreateEncoder(typ)
 		if encoder != nil {
@@ -265,4 +295,4 @@ func calcFieldNames(originalFieldName string, tagProvidedFieldName string) []str
 		fieldNames = []string{tagProvidedFieldName}
 	}
 	return fieldNames
-}
+}