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

Posted

技术标签:

【中文标题】无效操作:type interface 不支持索引【英文标题】:invalid operation: type interface does not support indexing无效操作:type interface 不支持索引 【发布时间】:2018-05-24 15:58:09 【问题描述】:

我是 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)

【问题讨论】:

这是一个不错的资源gobyexample.com/json @jeff 我正在使用界面,假设我不知道响应的结构。 @Jeff 它可以工作,但假设我必须解析嵌套元素,这个解决方案会很复杂。你有其他解决方案吗? 【参考方案1】:

你也可以这样做:

var inputJson string = "..."

var decoded map[string]map[string]interface

json.Unmarshal([]byte(inputJson), &decoded)

test := decoded["data"]["type"]

fmt.Println(test)
// output: domains

【讨论】:

【参考方案2】:

dinterface 类型,所以你不能像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 库很有用(其主要目标是帮助处理动态对象)。

【讨论】:

给像我这样的新手的提示:要理解这段代码为什么有效,应该了解Decode 的工作原理,这与unmarshal 有关。 json.Unmarshal 文档解释了它如何存储数据。【参考方案3】:

你需要一些技巧来处理你的情况。 就像使用反射一样,您可以参考 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)
    

【讨论】:

这个问题与BSON或Mongo无关。如果你想在这种情况下引用一些使用反射的东西,你不妨阅读 json 包的源代码,因为它实际上是相关的。 我推荐阅读bson.M,因为提问者在cmets中说,nested interface,我认为bson.M是decode nested interface的一个例子 嵌套的处理是简单的递归。 JSON 也可以。 我是新手,对 bson.M 很熟悉,很抱歉浪费您的时间。

以上是关于无效操作:type interface 不支持索引的主要内容,如果未能解决你的问题,请参考以下文章

Go: 无效操作 - 类型 *map[key]value 不支持索引

字符串常用操作

[Amazon](500310) 无效操作:尚不支持此类IN/NOT IN查询;

无效的“Podfile”文件:套接字错误不支持操作

无效的捆绑包。捆绑包 xxx 不支持最低操作系统版本 (2020)

Redshift 中的 DAU WAU MAU 错误:[Amazon](500310) 无效操作:由于内部错误,不支持此类关联子查询模式;