无效操作:类型 interface {} 不支持索引

Roh*_*mar 4 json dictionary go unmarshalling type-assertion

我是 golang 的新手,在读取嵌套的 JSON 响应时遇到问题。

var d interface{}
json.NewDecoder(response.Body).Decode(&d)
test :=d["data"].(map[string]interface{})["type"]
Run Code Online (Sandbox Code Playgroud)

response.Body 看起来像这样

{
    "links": {
      "self": "/domains/test.one"
    },
    "data": {
        "type": "domains",
        "id": "test.one",
        "attributes": {
            "product": " Website",
            "package": "Professional",
            "created_at": "2016-08-19T11:37:01Z"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是这样的:

invalid operation: d["data"] (type interface {} does not support indexing)
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 13

d是 type interface{},所以你不能像 那样索引它d["data"],你需要另一个类型断言:

test := d.(map[string]interface{})["data"].(map[string]interface{})["type"]
fmt.Println(test)
Run Code Online (Sandbox Code Playgroud)

然后它会起作用。输出将为"domains". 查看Go Playground上的一个工作示例。

另请注意,如果您声明d为 type map[string]interface{},则可以省去第一个类型断言:

var d map[string]interface{}
if err := json.NewDecoder(response.Body).Decode(&d); err != nil {
    panic(err)
}
test := d["data"].(map[string]interface{})["type"]
fmt.Println(test)
Run Code Online (Sandbox Code Playgroud)

输出是一样的。在Go Playground上试试这个。

如果您需要多次执行这些和类似操作,您可能会发现我的github.com/icza/dyno库很有用(其主要目标是帮助处理动态对象)。


Ter*_*ang 0

你需要一些技巧来处理你的情况。就像使用 Reflect 一样,您可以参考golang mongo 驱动程序 mgo
中关于 bson.M 的 Marshall&&UnMarshall 代码

使用反射解码嵌套的代码示例如下:

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

func main() {
    keys := []string{"hello", "world", "dude", "kind", "cool"}
    a := make(map[string]interface{})
    a[keys[4]] = "perfect"
    b := make(map[string]interface{})
    b[keys[3]] = a
    c := make(map[string]interface{})
    c[keys[2]] = b
    d := make(map[string]interface{})
    d[keys[1]] = c
    e := make(map[string]interface{})
    e[keys[0]] = d
    fmt.Println(e)

    if buf, err := json.Marshal(e); nil == err {
        dd := make(map[string]interface{})
        err = json.Unmarshal(buf, &dd)
        if nil != err {
            fmt.Println("failed", err)
        }

        for k, v := range dd {
            travel(dd, k, v)
        }
        fmt.Println(dd)

    } else {
        fmt.Println("failed marshal")
    }
}

func travel(dd map[string]interface{}, key string, value interface{}) {
    vv := reflect.ValueOf(value)
    switch vv.Kind() {
    case reflect.Map:
        m := value.(map[string]interface{})
        dd[key] = m
        for k, v := range m {
            travel(m, k, v)
        }
    case reflect.String:
        dd[key] = value.(string)
    }
}
Run Code Online (Sandbox Code Playgroud)