如何在 Go 语言中进行嵌套迭代?

问题描述 投票:0回答:1

我正在尝试对另一个软件进行扩展,该软件向 Go 中的应用程序发送请求。在 Go 程序(我现在将其称为“程序”)中,一个目的是将 JSON 文件转换为可以迭代的格式。这是我正在使用的示例 JSON 格式:

{
  "name": "Game-Name",
  "tree": {
    "$className": "DataModel",

    "ReplicatedStorage": {
      "$path": "src/ReplicatedStorage"
    },

    "ServerScriptService": {
      "$path": "src/ServerScriptService"
    },

    "ReplicatedFirst": {
      "$path": "src/ReplicatedFirst"
    },

    "ServerStorage": {
      "$path": "src/ServerStorage"
    }
  }
}

想法是:

  • 迭代可以拾取“名字”
  • 迭代可以拾取“$className”
  • 对于“$path”的所有实例作为索引,在父
    src
    文件夹下创建一个文件夹,其中包含父地图的索引。例如,
    ReplicatedStorage
    是路径为
    src/ReplicatedStorage
  • 的文件夹的名称

下面是一个旨在执行此操作的过程函数:

func process(in interface{}) {
v := reflect.ValueOf(in)

    if v.Kind() == reflect.Map {
        for _, key := range v.MapKeys() {
            strct := v.MapIndex(key)
    
            index := key.Interface()
            value := reflect.ValueOf(strct.Interface())
    
            if index == "tree" {
                for _, treeKey := range value.MapKeys() {
                    treeIndex := treeKey.Interface()
    
                    fmt.Println("KEY")
                    fmt.Println(treeIndex)
    
                    if treeIndex != "$className" {
                        fmt.Println("bug")
                        fmt.Println(treeKey)
    
                        a := key.MapIndex(value) // panic serving ...: reflect: call of reflect.Value.MapIndex on string Value
                        b := reflect.ValueOf(a.Interface())
    
                        for _, key2 := range b.MapKeys() {
                            index2 := key2.Interface()
                            value2 := reflect.ValueOf(key2.Interface())
    
                            fmt.Println(index2)
                            fmt.Println(value2)
                        }
                    }
                }
            }
        }
    }

}

注释是错误的地方和内容。我还想理想地做的一件事是不必堆叠 for 循环,因为那是非常臭的代码。

我是 Go 的新手,所以我确定解决方案很简单哈哈,感谢帮助和反馈。

谢谢!

json go iteration
1个回答
-1
投票

使用 type assertions 而不是 reflect 包。使用 map indexing 查找值,而不是循环遍历键并查找匹配项。

func process(in interface{}) error {
    top, ok := in.(map[string]interface{})
    if !ok {
        return errors.New("expected object at top level")
    }
    tree, ok := top["tree"].(map[string]interface{})
    if !ok {
        return errors.New(".tree not found")
    }
    name, ok := top["name"]
    if !ok {
        return errors.New(".name not found")
    }
    className, ok := tree["$className"].(string)
    if !ok {
        return errors.New(".tree.$className not found")
    }
    for k, v := range tree {
        thing, ok := v.(map[string]interface{})
        if !ok {
            continue
        }
        path, ok := thing["$path"].(string)
        if !ok {
            continue
        }
        fmt.Println(name, className, k, path)
    }
    return nil
}

https://go.dev/play/p/9GFpccjNQZY

© www.soinside.com 2019 - 2024. All rights reserved.