【问题标题】:How to create a infinite nested json and access the same in go lang data structures?如何创建无限嵌套的 json 并在 go lang 数据结构中访问它?
【发布时间】:2018-02-01 11:43:47
【问题描述】:

如何创建无限嵌套的 json 并在 go lang 数据结构中访问它,

例如下面的示例 json 具有 3 个级别,通常它应该是动态的,用户可以通过从下拉列表中选择值来添加任何子节点,该下拉列表是 UI 上的下拉列表。

{
        "value": {
            "Id": "1",
            "Text": "abcd",
            "Parent": ""
        },
        "children": [
            {
                "value": {
                    "Id": "2",
                    "Text": "abcd",
                    "Parent": "1"
                },
                "children": [
                    {
                        "value": {
                            "Id": "3",
                            "Text": "abcd",
                            "Parent": "1"
                        }
                    }
                ]
            }
        ]
    }

go 中的结构:我已经创建了这个 go 数据结构,但它最多只能访问 3 个基于上述 json 的级别,我们可以让这个数据结构成为动态的,它应该处理无限嵌套的 json。

 type AutoGenerated struct {
        Value struct {
            ID     string `json:"Id"`
            Text   string `json:"Text"`
            Parent string `json:"Parent"`
        } `json:"value"`
        Children []struct {
            Value struct {
                ID     string `json:"Id"`
                Text   string `json:"Text"`
                Parent string `json:"Parent"`
            } `json:"value"`
            Children []struct {
                Value struct {
                    ID     string `json:"Id"`
                    Text   string `json:"Text"`
                    Parent string `json:"Parent"`
                } `json:"value"`
            } `json:"children"`
        } `json:"children"`
    }

注意:我们可以添加 n 个父节点和 n 个子节点,这在 Go 数据结构中是否可行?

您能建议最好和最简单的方法来实现它吗?

我们如何添加/删除/编辑任何父母或孩子? (上面的 json 示例将来自 UI)?添加/删除/编辑需要哪个 json 结构或 id 的任何父级或子级?

【问题讨论】:

    标签: json go data-structures


    【解决方案1】:

    你可以在 Go 中使用递归结构来表示这个 json(通过递归,我的意思是 Level 包含一个 []Level):

    type Value struct {
        ID     string
        Text   string
        Parent string
    }
    
    type Level struct {
        Value    Value `json:"value"`
        Children []Level
    }
    

    鉴于您列为字符串 j 的 json,我现在可以按如下方式对其进行解组:

    var root Level
    err := json.Unmarshal([]byte(j), &root)
    if err != nil {
        panic(err)
    }
    fmt.Println(root)
    fmt.Println(root.Children[0])
    fmt.Println(root.Children[0].Children[0])
    

    这个输出:

    {{1 abcd } [{{2 abcd 1} [{{3 abcd 1} []}]}]}
    {{2 abcd 1} [{{3 abcd 1} []}]}
    {{3 abcd 1} []}
    

    Go playground link

    【讨论】:

    • 例如:从 UI 来说,如果我们想添加任何新的子项,如何将其添加到现有结构中?基于我们需要更新哪个键?
    • 什么用户界面?你只提供了 json,没有别的。如果您想将孩子添加到给定的父母,请遍历树,直到找到具有匹配 ID 的值并将孩子添加到孩子的切片中。
    • 如何添加孩子?任何附加功能都可用吗?,对不起,我是 golang 的新手 :(
    • 附加到切片只是Children = append(Children, newChild)。我建议您参加 Go 之旅,这在 Appending to a slice 部分中有介绍。
    • 修改树只是迭代它和添加/删除/修改子节点的组合。这与解析 json 无关,在技术上是一个单独的问题。但是,它是 Go 的基本用法,强烈建议您参加 Go 之旅,我们不会为您编写该代码。
    【解决方案2】:

    除了@marc,您还可以将这两个结构Value & Level 组合在一个结构中。与 AutoGenerated 一样,您只需将 [ ]Level 用作 Children。

    type Level struct {
        Value struct {
            ID     string
            Text   string
            Parent string
        } `json:"value"`
        Children []Level
    }
    

    playground

    【讨论】:

      【解决方案3】:

      基于@Marc的数据结构,一个简单的add

      func (l *Level) Add(path,Id,Text string) error {
          if path=="" {
              l.Children = append(l.Children, Level{ Value: Value{Id,Text,l.Value.ID} })
              return nil
          }
          x:=strings.SplitN(path,".",2)
          name,remain:=x[0],""
          if len(x)>1 {
              remain = x[1]
          }
      
          for i:=range l.Children {
              if l.Children[i].Value.ID == name {
                  return l.Children[i].Add(remain,Id,Text)
              }
          }
          return errors.New("Not found")
      }
      
      func main() {
          var root Level
          err := json.Unmarshal([]byte(j), &root)
          if err != nil {
              panic(err)
          }
          fmt.Println(root)
          fmt.Println(root.Children[0])
          fmt.Println(root.Children[0].Children[0])
          fmt.Println(root.Add("2.3","4","xxx"))
          fmt.Println(root)
      }
      

      删除和修改基本相同。

      游乐场:https://play.golang.org/p/7sWRJ-9EQSv

      【讨论】:

      • 将接受无限的树状结构,就像一个分支可以有任意数量的节点。
      • 能否解释一下添加函数的逻辑?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 2019-05-22
      • 2023-03-17
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      相关资源
      最近更新 更多