golang json和切片界面

时间:2018-01-09 11:33:04

标签: json go interface

我无法迭代包含接口切片的接口片段。

尝试使用返回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
        }
    }
}

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

你可以添加一个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被完全解析。