运行时动态结构体支持数组!!!!!!!! #2
							
								
								
									
										43
									
								
								builder.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								builder.go
									
									
									
									
									
								
							| @ -238,14 +238,52 @@ func (b *builderImpl) Build() DynamicStruct { | |||||||
| 				// 说明是顶层了 | 				// 说明是顶层了 | ||||||
| 				b.AddField(builderCfg.Field, "", builderCfg.Builder.Build().New(), builderCfg.Tag, false) | 				b.AddField(builderCfg.Field, "", builderCfg.Builder.Build().New(), builderCfg.Tag, false) | ||||||
| 			} else { | 			} else { | ||||||
| 				// (非顶层) 父级结构存在, 将其追加到父级结构中即可, 向前看一步即为父级结构 | 				// 处理数组 | ||||||
| 				b.nestedStructTable[strings.Join(parentNameArr[:len(parentNameArr)-1], ".")].Builder.AddField(builderCfg.Field, "", builderCfg.Builder.Build().New(), builderCfg.Tag, false) | 				arrDeep := 0 | ||||||
|  | 				newParentNameArr := []string{} | ||||||
|  | 				for i := len(parentNameArr) - 1; i >= 0; i-- { | ||||||
|  | 					if parentNameArr[i] != ArraySplit { | ||||||
|  | 						newParentNameArr = parentNameArr[:i+1] | ||||||
|  | 						break | ||||||
|  | 					} | ||||||
|  | 					// 删除 | ||||||
|  | 					delete(b.nestedStructTable, strings.Join(parentNameArr[:i+1], ".")) | ||||||
|  | 					arrDeep++ | ||||||
|  | 				} | ||||||
|  | 				if arrDeep > 0 { | ||||||
|  | 					// 数组嵌套数组配置 | ||||||
|  | 					val := reflect.ValueOf(builderCfg.Builder.Build().New()).Elem().Interface() | ||||||
|  | 					for i := 0; i < arrDeep; i++ { | ||||||
|  | 						val = reflect.New(reflect.SliceOf(reflect.TypeOf(val))).Interface() | ||||||
|  | 					} | ||||||
|  | 					// 解除指针引用 | ||||||
|  | 					val = reflect.ValueOf(val).Elem().Interface() | ||||||
|  | 					newParamIndex := strings.Join(newParentNameArr, ".") | ||||||
|  | 					isTopIndex := len(newParentNameArr) == 1 | ||||||
|  | 					if isTopIndex { | ||||||
|  | 						// 顶层结构, 数组类型不存在还有其他属性情况, 直接追加字段, 并移除嵌套表里的定义 | ||||||
|  | 						b.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | ||||||
|  | 						delete(b.nestedStructTable, newParamIndex) | ||||||
|  | 						// b.nestedStructTable[newParamIndex].Builder.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | ||||||
|  | 					} else { | ||||||
|  | 						// 非顶层结构, 再上探一级 | ||||||
|  | 						b.nestedStructTable[strings.Join(newParentNameArr[:len(newParentNameArr)-1], ".")].Builder.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					// 非数组 | ||||||
|  | 					// (非顶层) 父级结构存在, 将其追加到父级结构中即可, 向前看一步即为父级结构 | ||||||
|  | 					b.nestedStructTable[strings.Join(parentNameArr[:len(parentNameArr)-1], ".")].Builder.AddField(builderCfg.Field, "", builderCfg.Builder.Build().New(), builderCfg.Tag, false) | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// 一级字段属性 | 	// 一级字段属性 | ||||||
| 	var structFields []reflect.StructField | 	var structFields []reflect.StructField | ||||||
| 	for _, field := range b.fields { | 	for _, field := range b.fields { | ||||||
|  | 		if strings.Contains(field.name, ArraySplit) { | ||||||
|  | 			// TODO : 临时过滤, 后续需要在正确逻辑处正确移除 | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
| 		structFields = append(structFields, reflect.StructField{ | 		structFields = append(structFields, reflect.StructField{ | ||||||
| 			Name:      field.name, | 			Name:      field.name, | ||||||
| 			PkgPath:   field.pkg, | 			PkgPath:   field.pkg, | ||||||
| @ -274,6 +312,7 @@ func (f *fieldConfigImpl) SetTag(tag string) FieldConfig { | |||||||
|  |  | ||||||
| // New 创建动态结构体实例 | // New 创建动态结构体实例 | ||||||
| func (ds *dynamicStructImpl) New() any { | func (ds *dynamicStructImpl) New() any { | ||||||
|  | 	// 不要指针,全部解引用 | ||||||
| 	return reflect.New(ds.definition).Interface() | 	return reflect.New(ds.definition).Interface() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -10,11 +10,12 @@ package dynamicstruct | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func Test_dynamicStructImpl_New(t *testing.T) { | func Test_dynamicStructImpl_New(t *testing.T) { | ||||||
| 	instance := NewStruct(). | 	instance := NewStruct(map[string]string{}). | ||||||
| 		/*AddField("Integer", "", 0, `json:"int"`, false). | 		/*AddField("Integer", "", 0, `json:"int"`, false). | ||||||
| 		AddField("Text", "", "", `json:"someText"`, false). | 		AddField("Text", "", "", `json:"someText"`, false). | ||||||
| 		AddField("Float", "", 0.0, `json:"double"`, false). | 		AddField("Float", "", 0.0, `json:"double"`, false). | ||||||
| @ -25,10 +26,11 @@ func Test_dynamicStructImpl_New(t *testing.T) { | |||||||
| 		AddField("user.base.name", "", "", `json:"name"`, false). | 		AddField("user.base.name", "", "", `json:"name"`, false). | ||||||
| 		AddField("user.job.address", "", "", `json:"address"`, false). | 		AddField("user.job.address", "", "", `json:"address"`, false). | ||||||
| 		AddField("user.job.company.name", "", "", `json:"name"`, false). | 		AddField("user.job.company.name", "", "", `json:"name"`, false). | ||||||
|  | 		AddField("arr.[].item.name", "", "", `json:"name"`, false). | ||||||
|  | 		AddField("arr2.[].[].item.name", "", "", `json:"name"`, false). | ||||||
| 		Build() | 		Build() | ||||||
|  |  | ||||||
| 	val := instance.New() | 	val := instance.New() | ||||||
|  |  | ||||||
| 	data := []byte(` | 	data := []byte(` | ||||||
| { | { | ||||||
|     "int": 123, |     "int": 123, | ||||||
| @ -37,9 +39,13 @@ func Test_dynamicStructImpl_New(t *testing.T) { | |||||||
|     "Boolean": true, |     "Boolean": true, | ||||||
|     "Slice": [1, 2, 3], |     "Slice": [1, 2, 3], | ||||||
|     "user": {"job":{"address":"beijing","company":{"name":"unknown"}}, "base":{"age": 1800, "name":"baicha"}}, |     "user": {"job":{"address":"beijing","company":{"name":"unknown"}}, "base":{"age": 1800, "name":"baicha"}}, | ||||||
|     "Anonymous": "avoid to read" |     "Anonymous": "avoid to read", | ||||||
|  | 	"arr": [{"item":{"name":"item1","test":1}},{"item":{"name":"item2", "test":2}}], | ||||||
|  | 	"arr2": [[{"item":{"name":"item1","test":1}},{"item":{"name":"item2", "test":2}}]] | ||||||
| } | } | ||||||
| `) | `) | ||||||
|  | 	tType := reflect.TypeOf(val) | ||||||
|  | 	fmt.Println(tType, tType.Kind(), tType.Elem().Kind(), tType.Elem().Kind().String()) | ||||||
| 	err := json.Unmarshal(data, &val) | 	err := json.Unmarshal(data, &val) | ||||||
| 	fmt.Println(err, val) | 	fmt.Println(err, val) | ||||||
| 	valByte, _ := json.Marshal(val) | 	valByte, _ := json.Marshal(val) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user