在解组后访问嵌套JSON数组的Golang问题

时间:2014-06-24 03:32:18

标签: json go

我仍然处于Go的学习过程中,但在JSON响应数组方面却遇到了障碍。每当我尝试访问“objects”数组的嵌套元素时,Go throws(类型interface {}不支持索引)

出了什么问题,如何避免将来犯这个错误?

package main    

import (
        "encoding/json"
        "fmt"
)    

func main() {
        payload := []byte(`{"query": "QEACOR139GID","count": 1,"objects": [{"ITEM_ID": "QEACOR139GID","PROD_CLASS_ID": "BMXCPGRIPS","AVAILABLE": 19}]}`)
        var result map[string]interface{}
        if err := json.Unmarshal(payload, &result); err != nil {
            panic(err)
        }        

        fmt.Println(result["objects"]["ITEM_ID"])    

}

http://play.golang.org/p/duW-meEABJ

编辑:固定链接

2 个答案:

答案 0 :(得分:28)

如错误所示,接口变量不支持索引。您需要使用type assertion转换为基础类型。

解码为interface{}变量时,JSON模块将数组表示为[]interface{}个切片,将字典表示为map[string]interface{}个映射。

如果没有错误检查,您可以使用以下内容深入了解此JSON:

objects := result["objects"].([]interface{})
first := objects[0].(map[string]interface{})
fmt.Println(first["ITEM_ID"])

如果类型不匹配,这些类型断言将会发生混乱。您可以使用双返表单,您可以检查此错误。例如:

objects, ok := result["objects"].([]interface{})
if !ok {
    // Handle error here
}

如果JSON遵循已知格式,则更好的解决方案是解码为结构。根据您的示例中的数据,可能会执行以下操作:

type Result struct {
    Query   string `json:"query"`
    Count   int    `json:"count"`
    Objects []struct {
        ItemId      string `json:"ITEM_ID"`
        ProdClassId string `json:"PROD_CLASS_ID"`
        Available   int    `json:"AVAILABLE"`
    } `json:"objects"`
}

如果您解码为此类型,则可以将商品ID作为result.Objects[0].ItemId访问。

答案 1 :(得分:0)

对于那些可能寻找像我这样的类似解决方案的人,https://github.com/Jeffail/gabs提供了更好的解决方案。

我在这里提供了这个例子。

package main

import (
    "encoding/json"
    "fmt"

    "github.com/Jeffail/gabs"
)

func main() {
    payload := []byte(`{
        "query": "QEACOR139GID",
        "count": 1,
        "objects": [{
            "ITEM_ID": "QEACOR139GID",
            "PROD_CLASS_ID": "BMXCPGRIPS",
            "AVAILABLE": 19, 
            "Messages": [ {
                    "first": {
                        "text":  "sth, 1st"
                    }
                },
                {
                        "second": {
                        "text": "sth, 2nd"
                    }
              }
            ]
        }]
    }`)

    fmt.Println("Use gabs:")
    jsonParsed, _ := gabs.ParseJSON(payload)
    data := jsonParsed.Path("objects").Data()
    fmt.Println("  Fetch Data: ")
    fmt.Println("    ", data)
    children, _ := jsonParsed.Path("objects").Children()
    fmt.Println("  Children Array from \"Objects\": ")
    for key, child := range children {
        fmt.Println("    ", key, ": ", child)
        children2, _ := child.Path("Messages").Children()
        fmt.Println("    Children Array from \"Messages\": ")
        for key2, child2 := range children2 {
            fmt.Println("      ", key2, ": ", child2)
        }
    }
}