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

问题描述 投票:0回答:2

我是Golang的新手,在阅读嵌套的JSON响应时遇到了问题。

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

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"
        }
    }
}

我得到的错误是这样的:

invalid operation: d["data"] (type interface {} does not support indexing)
json dictionary go unmarshalling type-assertion
2个回答
4
投票

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

test := d.(map[string]interface{})["data"].(map[string]interface{})["type"]
fmt.Println(test)

然后它会工作。输出将是"domains"。请参阅Go Playground上的工作示例。

另请注意,如果您将d声明为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)

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

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


0
投票

你需要一些技巧来处理你的情况。 就像使用反射一样,你可以在golang mongo driver 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)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.