1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-23 11:37:32 +02:00

fix #207 delay unsupported type error reporting

This commit is contained in:
Tao Wen 2017-12-15 10:13:11 +08:00
parent e0df39fda2
commit a9b9c73b4d
11 changed files with 720 additions and 681 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,23 +7,17 @@ import (
"unsafe" "unsafe"
) )
func decoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) { func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder, err := decoderOfType(cfg, typ.Elem()) decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem())
if err != nil { return &arrayDecoder{typ, typ.Elem(), decoder}
return nil, err
}
return &arrayDecoder{typ, typ.Elem(), decoder}, nil
} }
func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
encoder, err := encoderOfType(cfg, typ.Elem()) encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem())
if err != nil {
return nil, err
}
if typ.Elem().Kind() == reflect.Map { if typ.Elem().Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder} encoder = &OptionalEncoder{encoder}
} }
return &arrayEncoder{typ, typ.Elem(), encoder}, nil return &arrayEncoder{typ, typ.Elem(), encoder}
} }
type arrayEncoder struct { type arrayEncoder struct {

View File

@ -240,7 +240,7 @@ func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncode
return nil return nil
} }
func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, error) { func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructDescriptor {
embeddedBindings := []*Binding{} embeddedBindings := []*Binding{}
bindings := []*Binding{} bindings := []*Binding{}
for i := 0; i < typ.NumField(); i++ { for i := 0; i < typ.NumField(); i++ {
@ -252,10 +252,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
} }
if field.Anonymous && (tag == "" || tagParts[0] == "") { if field.Anonymous && (tag == "" || tagParts[0] == "") {
if field.Type.Kind() == reflect.Struct { if field.Type.Kind() == reflect.Struct {
structDescriptor, err := describeStruct(cfg, field.Type) structDescriptor := describeStruct(cfg, prefix, field.Type)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...) binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty omitempty := binding.Encoder.(*structFieldEncoder).omitempty
@ -265,10 +262,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
} }
continue continue
} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { } else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
structDescriptor, err := describeStruct(cfg, field.Type.Elem()) structDescriptor := describeStruct(cfg, prefix, field.Type.Elem())
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...) binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty omitempty := binding.Encoder.(*structFieldEncoder).omitempty
@ -285,19 +279,11 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name) fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
decoder := fieldDecoders[fieldCacheKey] decoder := fieldDecoders[fieldCacheKey]
if decoder == nil { if decoder == nil {
var err error decoder = decoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
decoder, err = decoderOfType(cfg, field.Type)
if len(fieldNames) > 0 && err != nil {
return nil, err
}
} }
encoder := fieldEncoders[fieldCacheKey] encoder := fieldEncoders[fieldCacheKey]
if encoder == nil { if encoder == nil {
var err error encoder = encoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
encoder, err = encoderOfType(cfg, field.Type)
if len(fieldNames) > 0 && err != nil {
return nil, err
}
// map is stored as pointer in the struct, // map is stored as pointer in the struct,
// and treat nil or empty map as empty field // and treat nil or empty map as empty field
if encoder != nil && field.Type.Kind() == reflect.Map { if encoder != nil && field.Type.Kind() == reflect.Map {
@ -314,7 +300,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
binding.levels = []int{i} binding.levels = []int{i}
bindings = append(bindings, binding) bindings = append(bindings, binding)
} }
return createStructDescriptor(cfg, typ, bindings, embeddedBindings), nil return createStructDescriptor(cfg, typ, bindings, embeddedBindings)
} }
func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
onePtrEmbedded := false onePtrEmbedded := false

View File

@ -9,6 +9,22 @@ import (
"unsafe" "unsafe"
) )
func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder := decoderOfType(cfg, prefix+"[map]->", typ.Elem())
mapInterface := reflect.New(typ).Interface()
return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}
}
func encoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
elemType := typ.Elem()
encoder := encoderOfType(cfg, prefix+"[map]->", elemType)
mapInterface := reflect.New(typ).Elem().Interface()
if cfg.sortMapKeys {
return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
}
return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
}
type mapDecoder struct { type mapDecoder struct {
mapType reflect.Type mapType reflect.Type
keyType reflect.Type keyType reflect.Type

View File

@ -8,17 +8,14 @@ import (
"unsafe" "unsafe"
) )
func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
type bindingTo struct { type bindingTo struct {
binding *Binding binding *Binding
toName string toName string
ignored bool ignored bool
} }
orderedBindings := []*bindingTo{} orderedBindings := []*bindingTo{}
structDescriptor, err := describeStruct(cfg, typ) structDescriptor := describeStruct(cfg, prefix, typ)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames { for _, toName := range binding.ToNames {
new := &bindingTo{ new := &bindingTo{
@ -35,7 +32,7 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
} }
} }
if len(orderedBindings) == 0 { if len(orderedBindings) == 0 {
return &emptyStructEncoder{}, nil return &emptyStructEncoder{}
} }
finalOrderedFields := []structFieldTo{} finalOrderedFields := []structFieldTo{}
for _, bindingTo := range orderedBindings { for _, bindingTo := range orderedBindings {
@ -46,7 +43,8 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
}) })
} }
} }
return &structEncoder{structDescriptor.onePtrEmbedded, structDescriptor.onePtrOptimization, finalOrderedFields}, nil return &structEncoder{typ, structDescriptor.onePtrEmbedded,
structDescriptor.onePtrOptimization, finalOrderedFields}
} }
func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) { func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) {
@ -78,12 +76,9 @@ func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ig
} }
} }
func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) { func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
bindings := map[string]*Binding{} bindings := map[string]*Binding{}
structDescriptor, err := describeStruct(cfg, typ) structDescriptor := describeStruct(cfg, prefix, typ)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames { for _, fromName := range binding.FromNames {
old := bindings[fromName] old := bindings[fromName]
@ -131,6 +126,7 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
type structEncoder struct { type structEncoder struct {
typ reflect.Type
onePtrEmbedded bool onePtrEmbedded bool
onePtrOptimization bool onePtrOptimization bool
fields []structFieldTo fields []structFieldTo
@ -156,6 +152,9 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
isNotFirst = true isNotFirst = true
} }
stream.WriteObjectEnd() stream.WriteObjectEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error())
}
} }
func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) { func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) {

104
feature_reflect_optional.go Normal file
View File

@ -0,0 +1,104 @@
package jsoniter
import (
"reflect"
"unsafe"
)
func decoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
elemType := typ.Elem()
decoder := decoderOfType(cfg, prefix, elemType)
return &OptionalDecoder{elemType, decoder}
}
func encoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
elemType := typ.Elem()
elemEncoder := encoderOfType(cfg, prefix, elemType)
encoder := &OptionalEncoder{elemEncoder}
if elemType.Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return encoder
}
type OptionalDecoder struct {
ValueType reflect.Type
ValueDecoder ValDecoder
}
func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
*((*unsafe.Pointer)(ptr)) = nil
} else {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.ValueType)
newPtr := extractInterface(value.Interface()).word
decoder.ValueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
} else {
//reuse existing instance
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
}
type deferenceDecoder struct {
// only to deference a pointer
valueType reflect.Type
valueDecoder ValDecoder
}
func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.valueType)
newPtr := extractInterface(value.Interface()).word
decoder.valueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
} else {
//reuse existing instance
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
type OptionalEncoder struct {
ValueEncoder ValEncoder
}
func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *OptionalEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
type optionalMapEncoder struct {
valueEncoder ValEncoder
}
func (encoder *optionalMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *optionalMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *optionalMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
p := *((*unsafe.Pointer)(ptr))
return p == nil || encoder.valueEncoder.IsEmpty(p)
}

View File

@ -7,23 +7,17 @@ import (
"unsafe" "unsafe"
) )
func decoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) { func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
decoder, err := decoderOfType(cfg, typ.Elem()) decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
if err != nil { return &sliceDecoder{typ, typ.Elem(), decoder}
return nil, err
}
return &sliceDecoder{typ, typ.Elem(), decoder}, nil
} }
func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
encoder, err := encoderOfType(cfg, typ.Elem()) encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem())
if err != nil {
return nil, err
}
if typ.Elem().Kind() == reflect.Map { if typ.Elem().Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder} encoder = &OptionalEncoder{encoder}
} }
return &sliceEncoder{typ, typ.Elem(), encoder}, nil return &sliceEncoder{typ, typ.Elem(), encoder}
} }
type sliceEncoder struct { type sliceEncoder struct {

View File

@ -8,22 +8,22 @@ import (
"unsafe" "unsafe"
) )
func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (ValDecoder, error) { func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
knownHash := map[int32]struct{}{ knownHash := map[int32]struct{}{
0: {}, 0: {},
} }
switch len(fields) { switch len(fields) {
case 0: case 0:
return &skipObjectDecoder{typ}, nil return &skipObjectDecoder{typ}
case 1: case 1:
for fieldName, fieldDecoder := range fields { for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
} }
case 2: case 2:
var fieldHash1 int32 var fieldHash1 int32
@ -34,7 +34,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldHash1 == 0 { if fieldHash1 == 0 {
@ -45,7 +45,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldDecoder2 = fieldDecoder fieldDecoder2 = fieldDecoder
} }
} }
return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}
case 3: case 3:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -57,7 +57,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -72,7 +72,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &threeFieldsStructDecoder{typ, return &threeFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3}
case 4: case 4:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -86,7 +88,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -104,8 +106,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &fourFieldsStructDecoder{typ, return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4}, nil fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}
case 5: case 5:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -121,7 +125,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -142,8 +146,11 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &fiveFieldsStructDecoder{typ, return &fiveFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5}
case 6: case 6:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -161,7 +168,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -185,8 +192,12 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &sixFieldsStructDecoder{typ, return &sixFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6}
case 7: case 7:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -206,7 +217,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -233,9 +244,13 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &sevenFieldsStructDecoder{typ, return &sevenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName2, fieldDecoder2,
fieldName7, fieldDecoder7}, nil fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}
case 8: case 8:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -257,7 +272,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -287,9 +302,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &eightFieldsStructDecoder{typ, return &eightFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName2, fieldDecoder2,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8}
case 9: case 9:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -313,7 +333,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -346,9 +366,15 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &nineFieldsStructDecoder{typ, return &nineFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName2, fieldDecoder2,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8,
fieldName9, fieldDecoder9}
case 10: case 10:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -374,7 +400,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName) fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash] _, known := knownHash[fieldHash]
if known { if known {
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
knownHash[fieldHash] = struct{}{} knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 { if fieldName1 == 0 {
@ -410,12 +436,18 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &tenFieldsStructDecoder{typ, return &tenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName2, fieldDecoder2,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9, fieldName3, fieldDecoder3,
fieldName10, fieldDecoder10}, nil fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8,
fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}
} }
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}
} }
type generalStructDecoder struct { type generalStructDecoder struct {
@ -464,7 +496,7 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -502,7 +534,7 @@ func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -532,7 +564,7 @@ func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -566,7 +598,7 @@ func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -604,7 +636,7 @@ func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -646,7 +678,7 @@ func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -692,7 +724,7 @@ func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -742,7 +774,7 @@ func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -796,7 +828,7 @@ func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -854,7 +886,7 @@ func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }
@ -916,7 +948,7 @@ func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
} }
} }
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
} }
} }

View File

@ -109,12 +109,13 @@ func (extension *testExtension) UpdateStructDescriptor(structDescriptor *StructD
func Test_customize_field_by_extension(t *testing.T) { func Test_customize_field_by_extension(t *testing.T) {
should := require.New(t) should := require.New(t)
RegisterExtension(&testExtension{}) cfg := Config{}.Froze()
cfg.RegisterExtension(&testExtension{})
obj := TestObject1{} obj := TestObject1{}
err := UnmarshalFromString(`{"field-1": 100}`, &obj) err := cfg.UnmarshalFromString(`{"field-1": 100}`, &obj)
should.Nil(err) should.Nil(err)
should.Equal("100", obj.Field1) should.Equal("100", obj.Field1)
str, err := MarshalToString(obj) str, err := cfg.MarshalToString(obj)
should.Nil(err) should.Nil(err)
should.Equal(`{"field-1":100}`, str) should.Equal(`{"field-1":100}`, str)
} }

View File

@ -20,7 +20,7 @@ func Test_write_empty_interface_via_placeholder(t *testing.T) {
cacheKey: reflect.TypeOf(m).Elem(), cacheKey: reflect.TypeOf(m).Elem(),
} }
stream := ConfigFastest.BorrowStream(nil) stream := ConfigFastest.BorrowStream(nil)
encoderOfType(ConfigFastest.(*frozenConfig), reflect.TypeOf(m).Elem()) encoderOfType(ConfigFastest.(*frozenConfig), "", reflect.TypeOf(m).Elem())
encoder.EncodeInterface(inf, stream) encoder.EncodeInterface(inf, stream)
should.Equal(`"hello"`, string(stream.Buffer())) should.Equal(`"hello"`, string(stream.Buffer()))
} }

View File

@ -147,3 +147,40 @@ func Test_nil_pointer(t *testing.T) {
err := Unmarshal(data, obj) err := Unmarshal(data, obj)
should.NotNil(err) should.NotNil(err)
} }
func Test_func_pointer_type(t *testing.T) {
type TestObject2 struct {
F func()
}
type TestObject1 struct {
Obj *TestObject2
}
t.Run("encode null is valid", func(t *testing.T) {
should := require.New(t)
output, err := json.Marshal(TestObject1{})
should.Nil(err)
should.Equal(`{"Obj":null}`, string(output))
output, err = Marshal(TestObject1{})
should.Nil(err)
should.Equal(`{"Obj":null}`, string(output))
})
t.Run("encode not null is invalid", func(t *testing.T) {
should := require.New(t)
_, err := json.Marshal(TestObject1{Obj: &TestObject2{}})
should.NotNil(err)
_, err = Marshal(TestObject1{Obj: &TestObject2{}})
should.NotNil(err)
})
t.Run("decode null is valid", func(t *testing.T) {
should := require.New(t)
var obj TestObject1
should.Nil(json.Unmarshal([]byte(`{"Obj":{"F": null}}`), &obj))
should.Nil(Unmarshal([]byte(`{"Obj":{"F": null}}`), &obj))
})
t.Run("decode not null is invalid", func(t *testing.T) {
should := require.New(t)
var obj TestObject1
should.NotNil(json.Unmarshal([]byte(`{"Obj":{"F": "hello"}}`), &obj))
should.NotNil(Unmarshal([]byte(`{"Obj":{"F": "hello"}}`), &obj))
})
}