You've already forked json-iterator
mirror of
https://github.com/json-iterator/go.git
synced 2025-06-24 23:16:47 +02:00
#68 empty array to object/map
This commit is contained in:
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
"math"
|
"math"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxUint = ^uint(0)
|
const MaxUint = ^uint(0)
|
||||||
@ -13,6 +14,7 @@ const MaxInt = int(MaxUint >> 1)
|
|||||||
const MinInt = -MaxInt - 1
|
const MinInt = -MaxInt - 1
|
||||||
|
|
||||||
func RegisterFuzzyDecoders() {
|
func RegisterFuzzyDecoders() {
|
||||||
|
jsoniter.RegisterExtension(&tolerateEmptyArrayExtension{})
|
||||||
jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
|
jsoniter.RegisterTypeDecoder("string", &FuzzyStringDecoder{})
|
||||||
jsoniter.RegisterTypeDecoder("float32", &FuzzyFloat32Decoder{})
|
jsoniter.RegisterTypeDecoder("float32", &FuzzyFloat32Decoder{})
|
||||||
jsoniter.RegisterTypeDecoder("float64", &FuzzyFloat64Decoder{})
|
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 {
|
type FuzzyStringDecoder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,3 +85,17 @@ func Test_float_to_float64(t *testing.T) {
|
|||||||
should.Nil(jsoniter.UnmarshalFromString(`1.23`, &val))
|
should.Nil(jsoniter.UnmarshalFromString(`1.23`, &val))
|
||||||
should.Equal(float64(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}
|
decoder = &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
|
||||||
cfg.addDecoderToCache(cacheKey, decoder)
|
cfg.addDecoderToCache(cacheKey, decoder)
|
||||||
decoder, err := createDecoderOfType(cfg, typ)
|
decoder, err := createDecoderOfType(cfg, typ)
|
||||||
|
for _, extension := range extensions {
|
||||||
|
decoder = extension.DecorateDecoder(typ, decoder)
|
||||||
|
}
|
||||||
cfg.addDecoderToCache(cacheKey, decoder)
|
cfg.addDecoderToCache(cacheKey, decoder)
|
||||||
return decoder, err
|
return decoder, err
|
||||||
}
|
}
|
||||||
@ -330,6 +333,9 @@ func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
|||||||
encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
|
encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
|
||||||
cfg.addEncoderToCache(cacheKey, encoder)
|
cfg.addEncoderToCache(cacheKey, encoder)
|
||||||
encoder, err := createEncoderOfType(cfg, typ)
|
encoder, err := createEncoderOfType(cfg, typ)
|
||||||
|
for _, extension := range extensions {
|
||||||
|
encoder = extension.DecorateEncoder(typ, encoder)
|
||||||
|
}
|
||||||
cfg.addEncoderToCache(cacheKey, encoder)
|
cfg.addEncoderToCache(cacheKey, encoder)
|
||||||
return encoder, err
|
return encoder, err
|
||||||
}
|
}
|
||||||
|
@ -29,17 +29,19 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Binding struct {
|
type Binding struct {
|
||||||
Field *reflect.StructField
|
Field *reflect.StructField
|
||||||
FromNames []string
|
FromNames []string
|
||||||
ToNames []string
|
ToNames []string
|
||||||
Encoder ValEncoder
|
Encoder ValEncoder
|
||||||
Decoder ValDecoder
|
Decoder ValDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
type Extension interface {
|
type Extension interface {
|
||||||
UpdateStructDescriptor(structDescriptor *StructDescriptor)
|
UpdateStructDescriptor(structDescriptor *StructDescriptor)
|
||||||
CreateDecoder(typ reflect.Type) ValDecoder
|
CreateDecoder(typ reflect.Type) ValDecoder
|
||||||
CreateEncoder(typ reflect.Type) ValEncoder
|
CreateEncoder(typ reflect.Type) ValEncoder
|
||||||
|
DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder
|
||||||
|
DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder
|
||||||
}
|
}
|
||||||
|
|
||||||
type DummyExtension struct {
|
type DummyExtension struct {
|
||||||
@ -56,9 +58,18 @@ func (extension *DummyExtension) CreateEncoder(typ reflect.Type) ValEncoder {
|
|||||||
return nil
|
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 {
|
type funcDecoder struct {
|
||||||
fun DecoderFunc
|
fun DecoderFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
decoder.fun(ptr, iter)
|
decoder.fun(ptr, iter)
|
||||||
}
|
}
|
||||||
@ -120,6 +131,15 @@ func RegisterExtension(extension Extension) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
|
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 {
|
for _, extension := range extensions {
|
||||||
decoder := extension.CreateDecoder(typ)
|
decoder := extension.CreateDecoder(typ)
|
||||||
if decoder != nil {
|
if decoder != nil {
|
||||||
@ -141,6 +161,16 @@ func getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
|
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 {
|
for _, extension := range extensions {
|
||||||
encoder := extension.CreateEncoder(typ)
|
encoder := extension.CreateEncoder(typ)
|
||||||
if encoder != nil {
|
if encoder != nil {
|
||||||
|
Reference in New Issue
Block a user