我有一个嵌套的三层结构。 我想在Go中使用reflect来解析它(使用递归函数)。使用反射和递归函数的原因是
以下是一些代码。
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)
}
当我运行它时,在第一层我得到了&#34; 类型:* entity.SacWebIS &#34;。但是,在第二次迭代/递归中,我得到了&#34; 类型:* reflect.rtype &#34; 。
我也试过了field.Interface()
。
如何修改此代码?
感谢。
更新
解决方案是
CheckNestedStruct(dg, field.Addr().Interface())
答案 0 :(得分:1)
为了在不知道字段的值和类型的情况下解析未知的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{}
的切片或接口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
}
最后是接口{}的基础值,它将是基本类型string
,float64
,bool
。
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
}
}
}
上查看
答案 1 :(得分:1)
您在reflect.ValueOf
上呼叫reflect.Value
,这就是为您提供*reflect.rtype
类型的内容。如果您想将reflect.Value
传递回同一个函数,则需要先调用Interface()
。
CheckNestedStruct(field.Interface())
然后,无论您是在指针还是值上操作,都会调用Elem
。如果您想有条件地间接值,请使用reflect.Indirect
rv := reflect.Indirect(reflect.ValueOf(edges))
答案 2 :(得分:0)
上述代码(迭代函数)的简化版本:
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
}
}