修复嵌套结构体 + 嵌套数组的BUG #3
| @ -27,6 +27,10 @@ type IFieldConfig interface { | |||||||
| 	SetType(typ any) IFieldConfig | 	SetType(typ any) IFieldConfig | ||||||
| 	// SetTag 设置字段 tag. | 	// SetTag 设置字段 tag. | ||||||
| 	SetTag(tag string) IFieldConfig | 	SetTag(tag string) IFieldConfig | ||||||
|  | 	// GetType 获取类型 | ||||||
|  | 	GetType() any | ||||||
|  | 	// GetTag 获取tag | ||||||
|  | 	GetTag() string | ||||||
| } | } | ||||||
|  |  | ||||||
| // IDynamicStruct contains defined dynamic struct. | // 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)}) | 		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 | 	return f | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (f *fieldConfigImpl) GetType() any { | ||||||
|  | 	return f.typ | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetTag 设置字段标签 | // SetTag 设置字段标签 | ||||||
| func (f *fieldConfigImpl) SetTag(tag string) IFieldConfig { | func (f *fieldConfigImpl) SetTag(tag string) IFieldConfig { | ||||||
| 	f.tag = tag | 	f.tag = tag | ||||||
| 	return f | 	return f | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (f *fieldConfigImpl) GetTag() string { | ||||||
|  | 	return f.tag | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user