如何在不定义Golang结构的情况下读取json的“接口”映射?

如何在不定义Golang结构的情况下读取json的“接口”映射?,json,go,Json,Go,下面我将尝试读取Golang中的json文件。它说有两种方法可以做到这一点: 使用一组预定义的结构来解组JSON 或者使用map[string]接口{}解组JSON 因为我可能会有很多不同的json格式,所以我更喜欢动态地解释它。因此,我现在有以下代码: package main import ( "fmt" "os" "io/ioutil" "encoding/json" ) func main() { // Open our jsonFile

下面我将尝试读取Golang中的json文件。它说有两种方法可以做到这一点:

使用一组预定义的结构来解组JSON 或者使用map[string]接口{}解组JSON 因为我可能会有很多不同的json格式,所以我更喜欢动态地解释它。因此,我现在有以下代码:

package main

import (
    "fmt"
    "os"
    "io/ioutil"
    "encoding/json"
)

func main() {
    // Open our jsonFile
    jsonFile, err := os.Open("users.json")
    // if we os.Open returns an error then handle it
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("Successfully Opened users.json")
    // defer the closing of our jsonFile so that we can parse it later on
    defer jsonFile.Close()

    byteValue, _ := ioutil.ReadAll(jsonFile)

    var result map[string]interface{}
    json.Unmarshal([]byte(byteValue), &result)

    fmt.Println(result["users"])
    fmt.Printf("%T\n", result["users"])
}
这将打印出:

Successfully Opened users.json
[map[type:Reader age:23 social:map[facebook:https://facebook.com twitter:https://twitter.com] name:Elliot] map[name:Fraser type:Author age:17 social:map[facebook:https://facebook.com twitter:https://twitter.com]]]
[]interface {}
在这一点上,我不明白我怎么能读懂第一个用户23岁的年龄。我尝试了一些变化:

fmt.Println(result["users"][0])
fmt.Println(result["users"][0].age)
但显然,类型接口{}不支持索引

有没有一种方法可以在不定义结构的情况下访问json中的项?

可能是您想要的

fmt.Println(result["users"].(map[string]interface{})["age"])

由于JSON是映射的映射,因此叶节点的类型是接口{},因此必须转换为映射[string]接口{},以便查找键


定义结构要容易得多。我的首要技巧是使用一个将JSON转换为Go结构定义的网站,如

如果您对JSON的了解足够多,可以用这种方式解析,那么您就可以使用预定义的结构。这几乎总是首选方式。@Flimzy-几乎总是首选方式=>但为什么?如果没有它是可能的,那么为什么要定义它呢?或者不定义它就不可能吗?或者说定义它有很大的优势吗?如果是的话,它们是什么?因为正如您所发现的,使用预定义结构非常容易。但是,如果您喜欢结果[users].[interface{}[0].map[string]interface{}.[age],我绝对不会劝阻您不要过于冗长、难以阅读的代码:归根结底,Go是一种严格类型化的语言。这意味着您必须使用严格的类型,即使是JSON。您可以使用两种方法中的一种:使用自定义结构中定义的编译时类型,或者使用运行时反射。两者都要求您使用静态类型。在编译时执行此操作效率更高,因此速度更快,并且更易于阅读。所以只有在你必须的时候才使用反射。@Flimzy-谢谢你解释原因。我想方法是简单地定义它。第一个给出了一个恐慌:接口转换:接口{}是[]接口{},而不是映射[string]接口{},第二个给出了一个不能使用0类型int作为映射索引中的类型字符串。还有其他想法吗?
fmt.Println(result[0].(map[string]interface{})["age"])