Parcourir la source

#36 handle anonymous

Tao Wen il y a 8 ans
Parent
commit
59e71bacc8
3 fichiers modifiés avec 38 ajouts et 8 suppressions
  1. 22 7
      feature_reflect_object.go
  2. 1 1
      jsoniter_demo_test.go
  3. 15 0
      jsoniter_reflect_struct_test.go

+ 22 - 7
feature_reflect_object.go

@@ -11,12 +11,12 @@ import (
 
 func encoderOfStruct(typ reflect.Type) (Encoder, error) {
 	structEncoder_ := &structEncoder{}
-	for i := 0; i < typ.NumField(); i++ {
-		field := typ.Field(i)
+	fields := map[string]*structFieldEncoder{}
+	for _, field := range listStructFields(typ) {
 		fieldEncoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
 		var extensionProvidedFieldNames []string
 		for _, extension := range extensions {
-			alternativeFieldNames, fun, _ := extension(typ, &field)
+			alternativeFieldNames, fun, _ := extension(typ, field)
 			if alternativeFieldNames != nil {
 				extensionProvidedFieldNames = alternativeFieldNames
 			}
@@ -46,16 +46,31 @@ func encoderOfStruct(typ reflect.Type) (Encoder, error) {
 			}
 		}
 		for _, fieldName := range fieldNames {
-			structEncoder_.fields = append(structEncoder_.fields,
-				&structFieldEncoder{&field, fieldName, encoder, omitempty})
-		}
+			fields[fieldName] = &structFieldEncoder{field, fieldName, encoder, omitempty}
+			}
 	}
-	if len(structEncoder_.fields) == 0 {
+	if len(fields) == 0 {
 		return &emptyStructEncoder{}, nil
 	}
+	for _, field := range fields {
+		structEncoder_.fields = append(structEncoder_.fields, field)
+	}
 	return structEncoder_, nil
 }
 
+func listStructFields(typ reflect.Type) []*reflect.StructField {
+	fields := []*reflect.StructField{}
+	for i := 0; i < typ.NumField(); i++ {
+		field := typ.Field(i)
+		if field.Anonymous {
+			fields = append(fields, listStructFields(field.Type)...)
+		} else {
+			fields = append(fields, &field)
+		}
+	}
+	return fields
+}
+
 func decoderOfStruct(typ reflect.Type) (Decoder, error) {
 	fields := map[string]*structFieldDecoder{}
 	for i := 0; i < typ.NumField(); i++ {

+ 1 - 1
jsoniter_demo_test.go

@@ -21,4 +21,4 @@ func Test_iterator_api_demo(t *testing.T) {
 		total += iter.ReadInt()
 	}
 	fmt.Println(total)
-}
+}

+ 15 - 0
jsoniter_reflect_struct_test.go

@@ -223,3 +223,18 @@ func Test_one_field_struct(t *testing.T) {
 	should.Nil(err)
 	should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
 }
+
+func Test_anonymous_struct_marshal(t *testing.T) {
+	should := require.New(t)
+	type TestObject struct {
+		Field string
+	}
+	str, err := MarshalToString(struct{
+		TestObject
+		Field int
+	}{
+		Field: 100,
+	})
+	should.Nil(err)
+	should.Equal(`{"Field":100}`, str)
+}