You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	#68 empty array to object/map
This commit is contained in:
		| @@ -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 { | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user