修复嵌套结构体 + 嵌套数组的BUG #3
| @ -27,6 +27,10 @@ type IFieldConfig interface { | ||||
| 	SetType(typ any) IFieldConfig | ||||
| 	// SetTag 设置字段 tag. | ||||
| 	SetTag(tag string) IFieldConfig | ||||
| 	// GetType 获取类型 | ||||
| 	GetType() any | ||||
| 	// GetTag 获取tag | ||||
| 	GetTag() string | ||||
| } | ||||
|  | ||||
| // IDynamicStruct contains defined dynamic struct. | ||||
|  | ||||
							
								
								
									
										129
									
								
								builder_test.go
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								builder_test.go
									
									
									
									
									
								
							| @ -94,3 +94,132 @@ func TestStruct(t *testing.T) { | ||||
| 		So(res["slice"], ShouldEqual, []any{float64(1), float64(2), float64(3)}) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // TestNestedStruct : 测试嵌套结构体 | ||||
| func TestNestedStruct(t *testing.T) { | ||||
| 	Convey("嵌套结构体", t, func() { | ||||
| 		data := []byte(` | ||||
| 		{ | ||||
| "user": {"info": { | ||||
| 			"age": 123, | ||||
| 			"name": "example", | ||||
| 			"double": 123.45, | ||||
| 			"bool": true, | ||||
| 			"slice": [1, 2, 3] | ||||
| 		}}} | ||||
| 		`) | ||||
| 		instance := NewStruct(map[string]string{ | ||||
| 			"test_tag_map": `json:"tag_map"`, | ||||
| 		}). | ||||
| 			AddField("user.info.age", "", 0, `json:"age"`, false). | ||||
| 			AddField("user.info.name", "", "", `json:"name"`, false). | ||||
| 			Build() | ||||
| 		val := instance.New() | ||||
| 		err := json.Unmarshal(data, &val) | ||||
| 		So(err, ShouldBeNil) | ||||
| 		reflectType := reflect.TypeOf(val) | ||||
| 		// 需要是结构体类型 | ||||
| 		So(reflectType.Elem().Kind(), ShouldEqual, reflect.Struct) | ||||
| 		// 验证数据 | ||||
| 		// 数据序列化成功 | ||||
| 		targetByte, targetErr := json.Marshal(val) | ||||
| 		So(targetErr, ShouldBeNil) | ||||
| 		// 数据转map成功 | ||||
| 		var res map[string]any | ||||
| 		targetUnmarshalErr := json.Unmarshal(targetByte, &res) | ||||
| 		So(targetUnmarshalErr, ShouldBeNil) | ||||
| 		So(len(res), ShouldEqual, 1) | ||||
| 		So(res["user"], ShouldNotBeEmpty) | ||||
| 		userMap, ok := res["user"].(map[string]any) | ||||
| 		So(ok, ShouldBeTrue) | ||||
| 		So(len(userMap), ShouldEqual, 1) | ||||
| 		userInfoMap, ok := userMap["info"].(map[string]any) | ||||
| 		So(ok, ShouldBeTrue) | ||||
| 		So(userInfoMap["age"], ShouldEqual, float64(123)) | ||||
| 		So(userInfoMap["name"], ShouldEqual, "example") | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // TestStruct : 测试数组 | ||||
| func TestArray(t *testing.T) { | ||||
| 	Convey("嵌套结构体带多级数组", t, func() { | ||||
| 		data := []byte(` | ||||
| 		{ | ||||
| "user": {"list":[[[{ | ||||
| 			"age": 123, | ||||
| 			"name": "example", | ||||
| 			"double": 123.45, | ||||
| 			"bool": true, | ||||
| 			"slice": [1, 2, 3] | ||||
| 		}]]]} | ||||
| } | ||||
| 		`) | ||||
| 		instance := NewStruct(map[string]string{ | ||||
| 			"test_tag_map": `json:"tag_map"`, | ||||
| 		}). | ||||
| 			AddField("user.list.[].[].[].age", "", 0, `json:"age"`, false). | ||||
| 			AddField("user.list.[].[].[].name", "", "", `json:"name"`, false). | ||||
| 			Build() | ||||
| 		val := instance.New() | ||||
| 		err := json.Unmarshal(data, &val) | ||||
| 		So(err, ShouldBeNil) | ||||
| 		reflectType := reflect.TypeOf(val) | ||||
| 		// 需要是结构体类型 | ||||
| 		So(reflectType.Elem().Kind(), ShouldEqual, reflect.Struct) | ||||
| 		// 验证数据 | ||||
| 		// 数据序列化成功 | ||||
| 		targetByte, targetErr := json.Marshal(val) | ||||
| 		So(targetErr, ShouldBeNil) | ||||
| 		// 数据转map成功 | ||||
| 		var res map[string]map[string][][][]any | ||||
| 		targetUnmarshalErr := json.Unmarshal(targetByte, &res) | ||||
| 		So(targetUnmarshalErr, ShouldBeNil) | ||||
| 		So(len(res), ShouldEqual, 1) | ||||
| 		So(res["user"], ShouldNotBeEmpty) | ||||
| 		So(len(res["user"]), ShouldEqual, 1) | ||||
| 		So(len(res["user"]["list"][0]), ShouldEqual, 1) | ||||
| 		So(len(res["user"]["list"][0][0]), ShouldEqual, 1) | ||||
| 		userMap, ok := res["user"]["list"][0][0][0].(map[string]any) | ||||
| 		So(ok, ShouldBeTrue) | ||||
| 		So(len(userMap), ShouldEqual, 2) | ||||
| 		So(userMap["age"], ShouldEqual, float64(123)) | ||||
| 		So(userMap["name"], ShouldEqual, "example") | ||||
| 		So(userMap["double"], ShouldBeNil) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestFieldManage(t *testing.T) { | ||||
| 	Convey("结构体字段管理", t, func() { | ||||
| 		instance := NewStruct(map[string]string{ | ||||
| 			"test_tag_map": `json:"tag_map"`, | ||||
| 		}).AddField("age", "", 0, `json:"age"`, false). | ||||
| 			AddField("name", "", "", `json:"name"`, false) | ||||
| 		So(instance.HasField("Name"), ShouldBeTrue) | ||||
| 		So(instance.GetField("Name"), ShouldNotBeNil) | ||||
| 		instance.RemoveField("Name") | ||||
| 		So(instance.HasField("Name"), ShouldBeFalse) | ||||
| 		So(instance.GetField("Name"), ShouldBeNil) | ||||
| 		So(instance.HasField("Age"), ShouldBeTrue) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestExtendStruct(t *testing.T) { | ||||
| 	Convey("结构体字段继承", t, func() { | ||||
| 		type User struct { | ||||
| 			Name string `json:"name"` | ||||
| 			Age  int    `json:"age"` | ||||
| 		} | ||||
| 		type Company struct { | ||||
| 			Address string  `json:"address"` | ||||
| 			Logo    string  `json:"logo"` | ||||
| 			Age     float64 `json:"company_age"` // 应该覆盖掉 User.Age | ||||
| 		} | ||||
| 		instance := ExtendStruct(User{}, Company{}) | ||||
| 		So(instance.HasField("Name"), ShouldBeTrue) | ||||
| 		So(instance.HasField("Age"), ShouldBeTrue) | ||||
| 		So(instance.HasField("Address"), ShouldBeTrue) | ||||
| 		So(instance.HasField("Logo"), ShouldBeTrue) | ||||
| 		So(reflect.TypeOf(instance.GetField("Age").GetType()).Kind(), ShouldEqual, reflect.Float64) | ||||
| 		So(instance.GetField("Age").GetTag(), ShouldEqual, `json:"company_age"`) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @ -21,8 +21,16 @@ func (f *fieldConfigImpl) SetType(typ any) IFieldConfig { | ||||
| 	return f | ||||
| } | ||||
|  | ||||
| func (f *fieldConfigImpl) GetType() any { | ||||
| 	return f.typ | ||||
| } | ||||
|  | ||||
| // SetTag 设置字段标签 | ||||
| func (f *fieldConfigImpl) SetTag(tag string) IFieldConfig { | ||||
| 	f.tag = tag | ||||
| 	return f | ||||
| } | ||||
|  | ||||
| func (f *fieldConfigImpl) GetTag() string { | ||||
| 	return f.tag | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user