【问题标题】:How to access interface fields on json decode?如何访问json解码的接口字段?
【发布时间】:2015-04-04 11:35:29
【问题描述】:

我有一个 json 文档,我正在使用一个客户端,它在接口(而不是结构)中解码文档,如下所示:

var jsonR interface{}
err = json.Unmarshal(res, &jsonR)

如何访问界面字段?我已经阅读了 go doc 和 blog,但我的头脑仍然无法理解。他们的示例似乎仅表明您可以在接口中解码 json,但没有解释如何使用其字段。

我尝试使用范围循环,但当我到达 map[string] 界面时,故事似乎就结束了。我需要的字段似乎在界面中。

for k, v := range jsonR {
    if k == "topfield" {
        fmt.Printf("k  is %v, v is %v", k, v)

    }

}

【问题讨论】:

标签: json go


【解决方案1】:

接口内的值取决于你正在解析的 json 结构。如果你有一个 json 字典,jsonR 的动态类型将是:map[string]interface{}

这是一个例子。

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

func main() {
    a := []byte(`{"topfield": 123}`)
    var v interface{}
    if err := json.Unmarshal(a, &v); err != nil {
        log.Fatalf("unmarshal failed: %s", err)
    }
    fmt.Printf("value is %v", v.(map[string]interface{})["topfield"])
}

【讨论】:

  • 打印 topfield 我得到如下的东西,这似乎是界面本身。如何访问 obj 值? [map[_geoloc:map[fl:51 lg:33233] _tg:[xmaM] obj:FXX00X _hhg:map[mgs:[map[value:xmaMKA lcv:none mwo:[]]]]]]]
  • 您需要使用另一个type assertionv["topfield"] 转换为可以在其中进行另一次查找的地图或列表,并在每个级别重复:v.(map[string]interface{})["topfield"].([]interface{})[0].(map[string]interface{})["__geoloc"].(map[string]interface{})["fl"] 以获得v.topfield[0].__geoloc.fl在 JavaScript 中。缂。 (您实际上并不想让它成为一个大表达式,但 cmets 很短。:))
  • 另外,如果有趣的话,这是一个使用类型断言和类型开关来遍历映射键的程序:play.golang.org/p/_lxVlMe0i3。但是,它不会像您需要的那样递归,以便使用像您这样的深层结构。
【解决方案2】:

像这样解析 json 可能非常困难。解析的默认类型是map[string]interface{}。当您在主 json 中有另一个复杂的数据结构(如另一个列表或对象)时,就会出现问题。解码 json 的最佳方法是定义一个结构来保存数据。不仅值的类型正确,而且您可以提取您实际关心的特定数据。

您的结构可能如下所示:

type Top struct {
    Topfield int `json:"topfield"`
}

可以这样解码:

a := []byte(`{"topfield": 123}`)
var data Top
json.Unmarshal(a, &data) //parse the json into data

现在您可以使用常规结构操作来访问您的数据,如下所示:

value := data.Topfield

包含更复杂数据的json也可以easyli解码。也许您的数据中有一个列表,您可以使用如下结构来提取它:

type Data struct {
    States []string `json:"states"`
    PopulationData []Country `json:"popdata"`
}

type Country struct {
    Id int `json:"id"`
    LastCensusPop int `json:"lcensuspopulation"`
    Gdp  float64 `json:"gdp"`
}

这样的结构不仅可以解析列表,还可以解析带字段的对象。

【讨论】:

  • 我知道我可以使用结构来解码 json 并获取我关心的数据,但是我正在使用的客户端正在返回一个接口,所以我想知道我是否可以“将该接口绑定到一个结构。我不想使用的另一个选项是将接口再次编码为 JSON,然后使用结构对其进行解码,但这似乎不正确。
猜你喜欢
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
  • 2016-01-14
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 2021-05-30
相关资源
最近更新 更多