1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-14 11:18:49 +02:00

#81 handle field name conflict properly

This commit is contained in:
Tao Wen 2017-06-29 20:34:40 +08:00
parent e6c24947ee
commit 09cb1d9236
2 changed files with 100 additions and 44 deletions

View File

@ -31,6 +31,7 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
} }
type Binding struct { type Binding struct {
levels []int
Field *reflect.StructField Field *reflect.StructField
FromNames []string FromNames []string
ToNames []string ToNames []string
@ -206,6 +207,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
return nil, err return nil, err
} }
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, false} binding.Encoder = &structFieldEncoder{&field, binding.Encoder, false}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder} binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
if field.Offset == 0 { if field.Offset == 0 {
@ -221,12 +223,11 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
return nil, err return nil, err
} }
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
cloneField := field binding.levels = append([]int{i}, binding.levels...)
cloneField.Name = binding.Field.Name
binding.Encoder = &optionalEncoder{binding.Encoder} binding.Encoder = &optionalEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{&cloneField, binding.Encoder, false} binding.Encoder = &structFieldEncoder{&field, binding.Encoder, false}
binding.Decoder = &deferenceDecoder{field.Type.Elem(), binding.Decoder} binding.Decoder = &deferenceDecoder{field.Type.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{&cloneField, binding.Decoder} binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
if field.Offset == 0 { if field.Offset == 0 {
headAnonymousBindings = append(headAnonymousBindings, binding) headAnonymousBindings = append(headAnonymousBindings, binding)
} else { } else {
@ -266,6 +267,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
Decoder: decoder, Decoder: decoder,
Encoder: encoder, Encoder: encoder,
} }
binding.levels = []int{i}
bindings = append(bindings, binding) bindings = append(bindings, binding)
} }
return createStructDescriptor(cfg, typ, bindings, headAnonymousBindings, tailAnonymousBindings), nil return createStructDescriptor(cfg, typ, bindings, headAnonymousBindings, tailAnonymousBindings), nil

View File

@ -8,48 +8,102 @@ import (
) )
func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
fieldsByToName := map[string]int{} type bindingTo struct {
orderedFields := []*structFieldTo{} binding *Binding
toName string
ignored bool
}
orderedBindings := []*bindingTo{}
structDescriptor, err := describeStruct(cfg, typ) structDescriptor, err := describeStruct(cfg, typ)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for index, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames { for _, toName := range binding.ToNames {
oldIndex, found := fieldsByToName[toName] new := &bindingTo{
if found { binding: binding,
orderedFields[oldIndex] = nil // replaced by the later one toName: toName,
} }
fieldsByToName[toName] = index for _, old := range orderedBindings {
orderedFields = append(orderedFields, &structFieldTo{ if old.toName != toName {
binding.Encoder.(*structFieldEncoder), continue
toName, }
}) old.ignored, new.ignored = resolveConflictBinding(old.binding, new.binding)
}
orderedBindings = append(orderedBindings, new)
} }
} }
if len(orderedFields) == 0 { if len(orderedBindings) == 0 {
return &emptyStructEncoder{}, nil return &emptyStructEncoder{}, nil
} }
finalOrderedFields := []structFieldTo{} finalOrderedFields := []structFieldTo{}
for _, structFieldTo := range orderedFields { for _, bindingTo := range orderedBindings {
if structFieldTo != nil { if !bindingTo.ignored {
finalOrderedFields = append(finalOrderedFields, *structFieldTo) finalOrderedFields = append(finalOrderedFields, structFieldTo{
encoder: bindingTo.binding.Encoder.(*structFieldEncoder),
toName: bindingTo.toName,
})
}
}
return &structEncoder{structDescriptor.onePtrEmbedded, structDescriptor.onePtrOptimization, finalOrderedFields}, nil
}
func resolveConflictBinding(old, new *Binding) (ignoreOld, ignoreNew bool) {
newTagged := new.Field.Tag.Get("json") != ""
oldTagged := old.Field.Tag.Get("json") != ""
if newTagged {
if oldTagged {
if len(old.levels) > len(new.levels) {
return true, false
} else if len(new.levels) > len(old.levels) {
return false, true
} else {
return true, true
}
} else {
return true, false
}
} else {
if oldTagged {
return true, false
} else {
if len(old.levels) > len(new.levels) {
return true, false
} else if len(new.levels) > len(old.levels) {
return false, true
} else {
return true, true
}
} }
} }
return &structEncoder{structDescriptor.onePtrEmbedded,structDescriptor.onePtrOptimization,finalOrderedFields}, nil
} }
func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) { func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
fields := map[string]*structFieldDecoder{} bindings := map[string]*Binding{}
structDescriptor, err := describeStruct(cfg, typ) structDescriptor, err := describeStruct(cfg, typ)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames { for _, fromName := range binding.FromNames {
fields[fromName] = binding.Decoder.(*structFieldDecoder) old := bindings[fromName]
if old == nil {
bindings[fromName] = binding
continue
}
ignoreOld, ignoreNew := resolveConflictBinding(old, binding)
if ignoreOld {
delete(bindings, fromName)
}
if !ignoreNew {
bindings[fromName] = binding
}
} }
} }
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}
return createStructDecoder(typ, fields) return createStructDecoder(typ, fields)
} }
@ -120,7 +174,7 @@ 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}, nil
case 4: case 4:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -153,8 +207,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &fourFieldsStructDecoder{typ, return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil fieldName4, fieldDecoder4}, nil
case 5: case 5:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -192,8 +246,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &fiveFieldsStructDecoder{typ, return &fiveFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
case 6: case 6:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -236,8 +290,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &sixFieldsStructDecoder{typ, return &sixFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
case 7: case 7:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -285,9 +339,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &sevenFieldsStructDecoder{typ, return &sevenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}, nil fieldName7, fieldDecoder7}, nil
case 8: case 8:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -340,9 +394,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &eightFieldsStructDecoder{typ, return &eightFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
case 9: case 9:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -400,9 +454,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &nineFieldsStructDecoder{typ, return &nineFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
case 10: case 10:
var fieldName1 int32 var fieldName1 int32
var fieldName2 int32 var fieldName2 int32
@ -465,10 +519,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
} }
} }
return &tenFieldsStructDecoder{typ, return &tenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9, fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}, nil fieldName10, fieldDecoder10}, nil
} }
return &generalStructDecoder{typ, fields}, nil return &generalStructDecoder{typ, fields}, nil
} }
@ -992,9 +1046,9 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
type structEncoder struct { type structEncoder struct {
onePtrEmbedded bool onePtrEmbedded bool
onePtrOptimization bool onePtrOptimization bool
fields []structFieldTo fields []structFieldTo
} }
type structFieldTo struct { type structFieldTo struct {