【问题标题】:golang json and slices of interfacegolang json和接口切片
【发布时间】:2018-06-18 10:26:06
【问题描述】:

我在迭代包含接口切片的接口切片时遇到问题。

这个问题是在尝试使用返回 JSON 数据的 API 调用时出现的。返回的数据非常多,并且结构因请求而异。 API 文档中也没有 JSON 响应的结构,因此我正在尝试实现一些方法来处理任意 JSON 响应。

目前,在进行初始调用时,会将其放入 map[string]interface{} 中,然后运行 ​​switch 语句来确定每个元素的类型,当遇到接口切片时会出现问题。我似乎对他们无能为力。

我尝试过几次使用 sort 包(特别是 sort 和 slicestable 函数),但无济于事。

我收到的错误是:

interface conversion: interface {} is []interface {}, not map[string]interface {}

当我尝试映射接口切片时会发生这种情况,以便我可以再次使用 switch 语句对其进行迭代。

output := make(map[string]interface{})
err = json.Unmarshal(body, &output)

fmt.Println(err)
identify(output)

return err
}

func identify(output map[string]interface{}) {
    fmt.Printf("%T", output)
    for a, b := range output {
        switch bb := b.(type) {
        case string:
            fmt.Println("This is a string")
        case float64:
            fmt.Println("this is a float")
        case []interface{}:
            fmt.Println(" is []interface ", bb)
            test := b.(map[string]interface{}) // falis here
            fmt.Println("Success!", test)
        default:
            return
        }
    }
}

所以基本问题是如何在事先不知道结构的情况下迭代嵌套的接口切片?

【问题讨论】:

  • 如果case []interface{}: 则执行test := b.([]interface{}),而不是map...。你知道你可以迭代一个切片和一个映射,所以不要为了迭代而尝试将一个切片断言为映射。
  • 也许你想要的是bb[0].(map[string]interface{}),使用切片的元素而不是再次解析切片。

标签: json go interface


【解决方案1】:

好吧,您不能将 []interface{} 转换为 map[string]interface{}。因为它是一个切片,所以你可以遍历它的元素(注意 bbb 已经转换为适当的类型,你不需要再次转换 b):

    case []interface{}:
        fmt.Println(" is []interface ", bb)
        for _, val := range bb {
            // do something with val
        }
    default:
    ...

为什么你必须处理你不知道的事情?您是否有可能重新考虑您的架构并使用已知类型? 你见过example of delaying unmarshaling using json.RawMessage吗?或者试试implementing the Unmarshaler interface

【讨论】:

    【解决方案2】:

    您可以添加一个 switch case 检查接口切片的接口类型,然后运行与递归相同的函数,直到解析整个 json。

    output := make(map[string]interface{})
    err = json.Unmarshal(body, &output)
    
    fmt.Println(err)
    identify(output)
    
    return err
    }
    
    func identify(output map[string]interface{}) {
        fmt.Printf("%T", output)
        for a, b := range output {
            switch bb := b.(type) {
            case string:
                fmt.Println("This is a string")
            case float64:
                fmt.Println("this is a float")
            case []interface{}:
            // Access the values in the JSON object and place them in an Item
            for _, itemValue := range jsonObj {
                fmt.Printf("%v is an interface\n", itemValue)
                identify(itemValue.(map[string]interface{}))
            }
            default:
                return
            }
        }
    }
    

    可以有深度嵌套的json。我们只需要为每种情况创建选项,直到 json 被完全解析。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-21
      • 2017-08-29
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 2016-07-17
      • 1970-01-01
      • 2020-09-24
      相关资源
      最近更新 更多