doujishan2247 2016-09-29 04:21
浏览 56
已采纳

使用多层嵌套地图取消编组JSON

I realize that this question is very similar to others on stackoverflow but I have not been able to model the other questions to my use case.

I have JSON that looks like this (simplified for this post)

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

I am trying to get the hashes under groups into an array so I can iterate through and check the status of the hosts.
Based on some of the other posts here I felt I was on the correct track with this 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)

}

but I only end up with an empty data structure:

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

To see if I was even on the correct track I modified my JSON and took out the state key so that groups was the at the top level.
When I do that it populates the data structure as seen here

I'm struggling to understand why I can deal with the 1 level of nesting but not the second level?
My caveman brain thinks I should be able to reuse the pattern for as many levels of nesting I have.
At this point I've been fiddling most of the day and feel like I'm missing something that's right in front of me but can't see it.
Any pointers would be appreciated on how to handle the additional layer of nesting.

  • 写回答

2条回答 默认 最新

  • dotxxh0998 2016-09-29 04:56
    关注

    1 - You may remove one extra level by using:

    var data map[string]GroupsData
    

    Try it on 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
                }
            }
        }
    }`
    

    output:

    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 - You may use:

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

    Try it on 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
          }
        }
      }
    }`
    

    output:

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

    Your code works with one extra level "state": {} in JSON data: The Go Playground

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大