【问题标题】:How to read "interfaces" map of json without defining structure in Golang?如何在没有在 Golang 中定义结构的情况下读取 json 的“接口”映射?
【发布时间】:2018-12-09 11:55:18
【问题描述】:

this tutorial 之后,我正在尝试在 Golang 中读取 json 文件。它说有两种方法可以做到这一点:

  1. 使用一组预定义结构解组 JSON
  2. 或使用 map[string]interface 解组 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)

但显然,type interface {} does not support indexing

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

【问题讨论】:

  • 如果您对 JSON 足够了解以这种方式解析它,那么您就可以使用预定义的结构。这几乎总是首选方式。
  • @Flimzy - "almost always the preferred way" => 但是为什么呢?如果没有它是可能的,那为什么要定义它呢?还是没有定义就不可能?或者实际定义它有很大的优势吗?如果是这样,它们是什么?
  • 因为正如您所发现的,使用预定义结构非常容易。但是,如果你喜欢result["users"].([]interface{})[0].(map[string]interface{}).["age"]),我绝不会劝你不要使用过于冗长、难以阅读的代码。 :)
  • 真正归结为:Go 是一种严格类型的语言。这意味着您必须使用严格类型,即使是 JSON。您可以通过以下两种方式之一执行此操作:使用自定义结构中定义的编译时类型,或使用运行时反射。两者都要求您“获取”静态类型。在编译时执行它更有效(因此更快),并且更容易阅读。所以只在必要时使用反射。
  • @Flimzy - 感谢您解释原因。我想接下来的路就是简单地定义它。

标签: json go


【解决方案1】:

也许你想要

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

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

由于 JSON 是映射的映射,叶节点的类型是 interface{},因此必须将其转换为 map[string]interface{} 才能查找键

定义结构要容易得多。我这样做的首要技巧是使用将 JSON 转换为 Go 结构定义的网站,例如 Json-To-Go

【讨论】:

  • 第一个给出panic: interface conversion: interface {} is []interface {}, not map[string]interface {},第二个给出cannot use 0 (type int) as type string in map index。还有其他想法吗?
猜你喜欢
  • 1970-01-01
  • 2014-06-06
  • 2019-03-09
  • 1970-01-01
  • 2015-06-06
  • 2018-03-08
  • 1970-01-01
  • 2021-01-27
  • 2023-03-08
相关资源
最近更新 更多