支持传入的跟结构就是数组 #4
							
								
								
									
										44
									
								
								builder.go
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								builder.go
									
									
									
									
									
								
							| @ -178,6 +178,9 @@ func (b *builderImpl) Build() IDynamicStruct { | |||||||
| 	for deep := b.maxFieldDeep - 1; deep > 0; deep-- { | 	for deep := b.maxFieldDeep - 1; deep > 0; deep-- { | ||||||
| 		// 嵌套数据结构 | 		// 嵌套数据结构 | ||||||
| 		for parentIndex, builderCfg := range b.nestedStructTable { | 		for parentIndex, builderCfg := range b.nestedStructTable { | ||||||
|  | 			if parentIndex == ArrayRootFlag { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
| 			parentNameArr := strings.Split(parentIndex, ".") | 			parentNameArr := strings.Split(parentIndex, ".") | ||||||
| 			if len(parentNameArr) != deep { | 			if len(parentNameArr) != deep { | ||||||
| 				// 从深度最深处向上处理 | 				// 从深度最深处向上处理 | ||||||
| @ -201,24 +204,40 @@ func (b *builderImpl) Build() IDynamicStruct { | |||||||
| 				} | 				} | ||||||
| 				if arrDeep > 0 { | 				if arrDeep > 0 { | ||||||
| 					// 数组嵌套数组配置 | 					// 数组嵌套数组配置 | ||||||
| 					val := reflect.ValueOf(builderCfg.Builder.Build().New()).Elem().Interface() | 					val := reflect.ValueOf(builderCfg.Builder.Build().New()).Interface() | ||||||
| 					for i := 0; i < arrDeep; i++ { | 					for i := 0; i < arrDeep; i++ { | ||||||
| 						val = reflect.New(reflect.SliceOf(reflect.TypeOf(val))).Interface() | 						val = reflect.New(reflect.SliceOf(reflect.TypeOf(val).Elem())).Interface() | ||||||
|  | 						// 删除数组记录 | ||||||
|  | 						arrPath := strings.Join(parentNameArr[:len(parentNameArr)-i], ".") | ||||||
|  | 						delete(b.nestedStructTable, arrPath) | ||||||
| 					} | 					} | ||||||
| 					// 解除指针引用 | 					newParentIndex := strings.Join(newParentNameArr, ".") | ||||||
| 					// val = reflect.ValueOf(val).Elem().Interface() |  | ||||||
| 					newParamIndex := strings.Join(newParentNameArr, ".") |  | ||||||
| 					isTopIndex := len(newParentNameArr) == 1 | 					isTopIndex := len(newParentNameArr) == 1 | ||||||
| 					if isTopIndex { | 					if isTopIndex { | ||||||
| 						// 顶层结构, 数组类型不存在还有其他属性情况, 直接追加字段, 并移除嵌套表里的定义 | 						// 顶层结构, 数组类型不存在还有其他属性情况, 直接追加字段, 并移除嵌套表里的定义 | ||||||
| 						b.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | 						b.AddField(b.nestedStructTable[newParentIndex].Field, "", val, b.nestedStructTable[newParentIndex].Tag, false) | ||||||
| 						// b.nestedStructTable[newParamIndex].Builder.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | 						// b.nestedStructTable[newParamIndex].Builder.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | ||||||
| 					} else { | 					} else { | ||||||
| 						// 非顶层结构, 再上探一级 | 						// 非顶层结构, 再上探一级 | ||||||
| 						b.nestedStructTable[strings.Join(newParentNameArr[:len(newParentNameArr)-1], ".")].Builder.AddField(b.nestedStructTable[newParamIndex].Field, "", val, b.nestedStructTable[newParamIndex].Tag, false) | 						newParentName := "" | ||||||
|  | 						fieldName := "" | ||||||
|  | 						if len(newParentNameArr) == 0 { | ||||||
|  | 							// 说明传入的直接就是数组 | ||||||
|  | 							newParentName = ArrayRootFlag | ||||||
|  | 							fieldName = ArrayRootFlag | ||||||
|  | 							b.nestedStructTable[newParentName] = nestedStruct{ | ||||||
|  | 								Field:   fieldName, | ||||||
|  | 								Builder: NewStruct(b.structTagTable), | ||||||
|  | 								Tag:     "", | ||||||
|  | 							} | ||||||
|  | 							b.nestedStructTable[newParentName].Builder.AddField(b.nestedStructTable[newParentName].Field, "", reflect.ValueOf(val).Elem().Interface(), b.nestedStructTable[newParentName].Tag, false) | ||||||
|  | 						} else { | ||||||
|  | 							newParentName = strings.Join(newParentNameArr[:len(newParentNameArr)-1], ".") | ||||||
|  | 							b.nestedStructTable[newParentName].Builder.AddField(b.nestedStructTable[newParentIndex].Field, "", reflect.ValueOf(val).Elem().Interface(), b.nestedStructTable[newParentIndex].Tag, false) | ||||||
|  | 						} | ||||||
| 					} | 					} | ||||||
| 					// 嵌套结构中删除数组字段 | 					// 嵌套结构中删除数组字段 | ||||||
| 					delete(b.nestedStructTable, newParamIndex) | 					delete(b.nestedStructTable, newParentIndex) | ||||||
| 				} else { | 				} else { | ||||||
| 					// 非数组 | 					// 非数组 | ||||||
| 					// (非顶层) 父级结构存在, 将其追加到父级结构中即可, 向前看一步即为父级结构 | 					// (非顶层) 父级结构存在, 将其追加到父级结构中即可, 向前看一步即为父级结构 | ||||||
| @ -227,6 +246,15 @@ func (b *builderImpl) Build() IDynamicStruct { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if nestedCfg, exist := b.nestedStructTable[ArrayRootFlag]; exist { | ||||||
|  | 		// 说明是传入的根路径就是数组 | ||||||
|  | 		return &dynamicStructImpl{ | ||||||
|  | 			structFields: nil, | ||||||
|  | 			definition:   reflect.TypeOf(nestedCfg.Builder.GetField(ArrayRootFlag).GetType()), | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// 一级字段属性 | 	// 一级字段属性 | ||||||
| 	var structFields []reflect.StructField | 	var structFields []reflect.StructField | ||||||
| 	for _, field := range b.fields { | 	for _, field := range b.fields { | ||||||
|  | |||||||
| @ -223,3 +223,45 @@ func TestExtendStruct(t *testing.T) { | |||||||
| 		So(instance.GetField("Age").GetTag(), ShouldEqual, `json:"company_age"`) | 		So(instance.GetField("Age").GetTag(), ShouldEqual, `json:"company_age"`) | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestArrayRoot(t *testing.T) { | ||||||
|  | 	Convey("嵌套结构体带多级数组", t, func() { | ||||||
|  | 		data := []byte(` | ||||||
|  | [[[{ | ||||||
|  | 			"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("[].[].[].age", "", 0, `json:"age"`, false). | ||||||
|  | 			AddField("[].[].[].name", "", "", `json:"name"`, false). | ||||||
|  | 			Build() | ||||||
|  | 		val := instance.New() | ||||||
|  | 		err := json.Unmarshal(data, &val) | ||||||
|  | 		So(err, ShouldBeNil) | ||||||
|  | 		reflectType := reflect.TypeOf(val) | ||||||
|  | 		// 需要是数组类型 | ||||||
|  | 		So(reflectType.Kind(), ShouldEqual, reflect.Ptr) | ||||||
|  | 		So(reflectType.Elem().Kind(), ShouldEqual, reflect.Slice) | ||||||
|  | 		// 验证数据 | ||||||
|  | 		// 数据序列化成功 | ||||||
|  | 		targetByte, targetErr := json.Marshal(val) | ||||||
|  | 		So(targetErr, ShouldBeNil) | ||||||
|  | 		// 数据转map成功 | ||||||
|  | 		var res [][][]any | ||||||
|  | 		targetUnmarshalErr := json.Unmarshal(targetByte, &res) | ||||||
|  | 		So(targetUnmarshalErr, ShouldBeNil) | ||||||
|  | 		So(len(res), ShouldEqual, 1) | ||||||
|  | 		userMap, ok := res[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) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | |||||||
| @ -3,4 +3,6 @@ package dynamicstruct | |||||||
| const ( | const ( | ||||||
| 	// ArraySplit is the string used to split array elements | 	// ArraySplit is the string used to split array elements | ||||||
| 	ArraySplit = "[]" | 	ArraySplit = "[]" | ||||||
|  | 	// ArrayRootFlag 传入路径直接以数组开头 | ||||||
|  | 	ArrayRootFlag = "__RootArrayFlag" | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -7,7 +7,9 @@ | |||||||
| // Date : 2025-03-23 14:14 | // Date : 2025-03-23 14:14 | ||||||
| package dynamicstruct | package dynamicstruct | ||||||
|  |  | ||||||
| import "reflect" | import ( | ||||||
|  | 	"reflect" | ||||||
|  | ) | ||||||
|  |  | ||||||
| type dynamicStructImpl struct { | type dynamicStructImpl struct { | ||||||
| 	structFields []reflect.StructField | 	structFields []reflect.StructField | ||||||
| @ -16,7 +18,6 @@ type dynamicStructImpl struct { | |||||||
|  |  | ||||||
| // New 创建动态结构体实例 | // New 创建动态结构体实例 | ||||||
| func (ds *dynamicStructImpl) New() any { | func (ds *dynamicStructImpl) New() any { | ||||||
| 	// 不要指针,全部解引用 |  | ||||||
| 	return reflect.New(ds.definition).Interface() | 	return reflect.New(ds.definition).Interface() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user