【问题标题】:Unmarshal JSON with many layers of nested maps使用多层嵌套映射解组 JSON
【发布时间】:2016-09-29 17:46:35
【问题描述】:

我意识到这个问题与 stackoverflow 上的其他问题非常相似,但我无法将其他问题建模到我的用例中。

我的 JSON 看起来像这样(为这篇文章进行了简化)

{
  "somekey": "string",
  "state": {
    "groups": {
      "host:host1": {
        "status": "OK",
        "morethings": "blah"
      },
      "host:host2": {
        "status": "Alert",
        "morethings": "blah"
      }
    }
  }
}

我正在尝试将 groups 下的哈希值放入一个数组中,这样我就可以遍历并检查主机的状态。
根据这里的其他一些帖子,我觉得我在这个example 的正确轨道上:

package main

import (
    "encoding/json"
    "fmt"
)

const jsonStream = `
{
  "state": {
    "groups": {
      "host:i-b3a6cea5": {
        "status": "OK",
        "last_triggered_ts": null,
        "last_nodata_ts": null,
        "name": "host:i-b3a6cea5",
        "last_notified_ts": null,
        "last_resolved_ts": null
      },
      "host:i-4d81ca7c": {
        "status": "OK",
        "last_triggered_ts": null,
        "last_nodata_ts": null,
        "name": "host:i-4d81ca7c",
        "last_notified_ts": null,
        "last_resolved_ts": null
      },
      "host:i-a03a7758": {
        "status": "Alert",
        "triggering_value": {
          "to_ts": 1475092440,
          "value": 2,
          "from_ts": 1475092380
        },
        "last_triggered_ts": 1475092440,
        "last_nodata_ts": null,
        "name": "host:i-a03a7758",
        "last_notified_ts": 1475092440,
        "last_resolved_ts": null
      }
    }
  }
}`

type hostDetails struct {
    Status string `json:"status"`
    Name   string `json:"name"`
}

type GroupsData struct {
    Groups map[string]hostDetails `json:"groups"`
}

type Data struct {
    State map[string]GroupsData `json:"state"`
}

func main() {
    var data Data

    err := json.Unmarshal([]byte(jsonStream), &data)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(data)

}

但我最终只会得到一个空的数据结构:

{map[groups:{map[]}]}

为了查看我是否在正确的轨道上,我修改了我的 JSON 并取出了 state 键,以便 groups 位于顶层。
当我这样做时,它会填充数据结构,如 here

所示

我很难理解为什么我可以处理 1 级嵌套但不能处理第二级?
我的穴居人大脑认为我应该能够在我拥有的尽可能多的嵌套级别中重复使用该模式。
在这一点上,我一天中的大部分时间都在摆弄,感觉我错过了一些就在我面前但看不到的东西。
任何关于如何处理额外嵌套层的指针都将不胜感激。

【问题讨论】:

    标签: json go


    【解决方案1】:

    1 - 您可以使用以下命令删除一个额外的级别:

    var data map[string]GroupsData
    

    试试The Go Playground:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    func main() {
        var data map[string]GroupsData
        err := json.Unmarshal([]byte(jsonStream), &data)
        if err != nil {
            fmt.Println(err)
        }    
        fmt.Println(data)    
    }
    
    type GroupsData struct {
        Groups map[string]HostDetails `json:"groups"`
    }
    
    type HostDetails struct {
        Status string `json:"status"`
        Name   string `json:"name"`
    }
    
    const jsonStream = `
    {
        "state": {
            "groups": {
                "host:i-b3a6cea5": {
                    "status": "OK",
                    "last_triggered_ts": null,
                    "last_nodata_ts": null,
                    "name": "host:i-b3a6cea5",
                    "last_notified_ts": null,
                    "last_resolved_ts": null
                },
                "host:i-4d81ca7c": {
                    "status": "OK",
                    "last_triggered_ts": null,
                    "last_nodata_ts": null,
                    "name": "host:i-4d81ca7c",
                    "last_notified_ts": null,
                    "last_resolved_ts": null
                },
                "host:i-a03a7758": {
                    "status": "Alert",
                    "triggering_value": {
                        "to_ts": 1475092440,
                        "value": 2,
                        "from_ts": 1475092380
                    },
                    "last_triggered_ts": 1475092440,
                    "last_nodata_ts": null,
                    "name": "host:i-a03a7758",
                    "last_notified_ts": 1475092440,
                    "last_resolved_ts": null
                }
            }
        }
    }`
    

    输出:

    map[state:{map[host:i-b3a6cea5:{OK host:i-b3a6cea5} host:i-4d81ca7c:{OK host:i-4d81ca7c} host:i-a03a7758:{Alert host:i-a03a7758}]}]
    

    2 - 你可以使用:

    type Data struct {
        State GroupsData `json:"state"`
    }   
    

    试试The Go Playground:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    func main() {
        var data Data    
        err := json.Unmarshal([]byte(jsonStream), &data)
        if err != nil {
            fmt.Println(err)
        }    
        fmt.Println(data)    
    }
    
    type Data struct {
        State GroupsData `json:"state"`
    }
    type GroupsData struct {
        Groups map[string]hostDetails `json:"groups"`
    }
    
    type hostDetails struct {
        Status string `json:"status"`
        Name   string `json:"name"`
    }
    
    const jsonStream = `
    {
      "state": {
        "groups": {
          "host:i-b3a6cea5": {
            "status": "OK",
            "last_triggered_ts": null,
            "last_nodata_ts": null,
            "name": "host:i-b3a6cea5",
            "last_notified_ts": null,
            "last_resolved_ts": null
          },
          "host:i-4d81ca7c": {
            "status": "OK",
            "last_triggered_ts": null,
            "last_nodata_ts": null,
            "name": "host:i-4d81ca7c",
            "last_notified_ts": null,
            "last_resolved_ts": null
          },
          "host:i-a03a7758": {
            "status": "Alert",
            "triggering_value": {
              "to_ts": 1475092440,
              "value": 2,
              "from_ts": 1475092380
            },
            "last_triggered_ts": 1475092440,
            "last_nodata_ts": null,
            "name": "host:i-a03a7758",
            "last_notified_ts": 1475092440,
            "last_resolved_ts": null
          }
        }
      }
    }`
    

    输出:

    {{map[host:i-b3a6cea5:{OK host:i-b3a6cea5} host:i-4d81ca7c:{OK host:i-4d81ca7c} host:i-a03a7758:{Alert host:i-a03a7758}]}}
    

    您的code 与 JSON 数据中的一个额外级别 "state": {} 一起使用:The Go Playground

    【讨论】:

      【解决方案2】:

      您的错误是Data.State 不应该是地图。如果您将定义更改为

      type Data struct {
          State GroupsData `json:"state"`
      }
      

      有效:https://play.golang.org/p/oRjSJMDzU8

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-08
        • 2015-05-29
        • 2018-03-09
        • 2022-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多