如何使用reflect递归解析Go中的嵌套结构?
我有一个嵌套的三层结构。 我想在Go中使用reflect来解析它,使用递归函数。使用reflect和递归函数的原因如下 可以有不同数量的字段,但前两个字段是固定的 字段类型不是固定的。 在本例中,嵌套层的数量可以不同,仅三层。它可以是更多 这里有一些代码如何使用reflect递归解析Go中的嵌套结构?,go,struct,reflection,recursive-datastructures,Go,Struct,Reflection,Recursive Datastructures,我有一个嵌套的三层结构。 我想在Go中使用reflect来解析它,使用递归函数。使用reflect和递归函数的原因如下 可以有不同数量的字段,但前两个字段是固定的 字段类型不是固定的。 在本例中,嵌套层的数量可以不同,仅三层。它可以是更多 这里有一些代码 type Edge struct{ Uid string `json:"uid,omitempty"` Name string `json:"name,omitempty"` Read Article `json:"v
type Edge struct{
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Read Article `json:"visited,omitempty"`
}
type Article struct {
Uid string`json:"uid,omitempty"`
Namestring`json:"name,omitempty"`
From Site `json:"from,omitempty"`
}
type Site struct{
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
}
func CheckNestedStruct(edges interface{}){
rv := reflect.ValueOf(edges).Elem()
uidField := rv.FieldByName("Uid")
uid := getStructField(edges, "Name") // get value of Name from database
if (uid != ""){
uidField.SetString(uid)
}
for i := 0 ; i < rv.NumField() ; i++ {
field := rv.Field(i)
fieldType := field.Kind()
if (fieldType == reflect.Struct){
CheckNestedStruct(field)
}
}
}
func main(){
....
var edges Edges{
...
...
}
CheckNestedStruct(&edges)
}
为了在不知道字段的值和类型的情况下解析未知json,您需要创建一个递归函数,该函数将通过深度嵌套的底层值进行解析。您可以使用类型断言获得最终值
func main() {
m, ok := myJson.(map[string]interface{})
newM := iterate(m)
jsonBytes, err := json.Marshal(newM)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(jsonBytes))
}
对于将json解组为接口的记录,它主要转换为嵌套结构的两种类型,即interface[]interface{}的切片或interface map[string]interface{}的映射,直到我们得到嵌套结构的最终值为止,我们可以使用interface获得该值。因此,我们可以为深层嵌套结构创建递归
func iterate(data interface{}) interface{} {
if reflect.ValueOf(data).Kind() == reflect.Slice {
d := reflect.ValueOf(data)
tmpData := make([]interface{}, d.Len())
returnSlice := make([]interface{}, d.Len())
for i := 0; i < d.Len(); i++ {
tmpData[i] = d.Index(i).Interface()
}
for i, v := range tmpData {
returnSlice[i] = iterate(v)
}
return returnSlice
} else if reflect.ValueOf(data).Kind() == reflect.Map {
d := reflect.ValueOf(data)
tmpData := make(map[string]interface{})
for _, k := range d.MapKeys() {
typeOfValue := reflect.TypeOf(d.MapIndex(k).Interface()).Kind()
if typeOfValue == reflect.Map || typeOfValue == reflect.Slice {
tmpData[k.String()] = iterate(d.MapIndex(k).Interface())
} else {
tmpData[k.String()] = d.MapIndex(k).Interface()
}
}
return tmpData
}
return data
}
检查您在reflect.Value上调用reflect.ValueOf的,它为您提供了*reflect.rtype类型。如果要将reflect.Value传递回同一个函数,则需要首先调用接口
然后,无论是对指针还是对值进行操作,都将调用Elem。如果要有条件地间接指定值,请使用reflect.indirect
上述代码迭代函数的更简单版本:
func iterate(data interface{}) interface{} {
d := reflect.ValueOf(data)
if reflect.ValueOf(data).Kind() == reflect.Slice {
returnSlice := make([]interface{}, d.Len())
for i := 0; i < d.Len(); i++ {
returnSlice[i] = iterate(d.Index(i).Interface())
}
return returnSlice
} else if reflect.ValueOf(data).Kind() == reflect.Map {
tmpData := make(map[string]interface{})
for _, k := range d.MapKeys() {
tmpData[k.String()] = iterate(d.MapIndex(k).Interface())
}
return tmpData
} else {
return data
}
}
上传纯代码.Thx。全部的我找到了答案。答案应选中NestedStructField.Addr.InterfaceHi,thx。我找到了答案。您的答案很接近,但应该是field.Addr。Interface@LuffyCyliu:这取决于你想完成什么。如果使用间接,则不需要Addr,如果遇到不可寻址的字段,它将死机。
func identify(output map[string]interface{}) {
fmt.Printf("%T", output)
for a, b := range output {
switch bb := b.(type) {
case string:
fmt.Println("This is a string")
case float64:
fmt.Println("this is a float")
case bool:
fmt.Println("this is a boolean")
case []interface{}:
// Access the values in the JSON object and place them in an Item
for _, itemValue := range jsonObj {
fmt.Printf("%v is an interface\n", itemValue)
identify(itemValue.(map[string]interface{}))
}
default:
return
}
}
}
CheckNestedStruct(field.Interface())
rv := reflect.Indirect(reflect.ValueOf(edges))
func iterate(data interface{}) interface{} {
d := reflect.ValueOf(data)
if reflect.ValueOf(data).Kind() == reflect.Slice {
returnSlice := make([]interface{}, d.Len())
for i := 0; i < d.Len(); i++ {
returnSlice[i] = iterate(d.Index(i).Interface())
}
return returnSlice
} else if reflect.ValueOf(data).Kind() == reflect.Map {
tmpData := make(map[string]interface{})
for _, k := range d.MapKeys() {
tmpData[k.String()] = iterate(d.MapIndex(k).Interface())
}
return tmpData
} else {
return data
}
}