在Golang中访问类型为map[string]interface{}的嵌套地图

38

我正在尝试解析一个JSON响应。它可能有多个嵌套层级。这是我所做的:

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

首先,这是正确的方法吗?

假设响应如下:

{
  "args": {
            "foo": "bar"
          }
}

访问关键字foo,我看到一个playground这样做:

result["args"].(map[string]interface{})["foo"]

这里,“.()”表示什么?这个正确吗?

2个回答

57
符号 x.(T) 被称为类型断言
对于一个接口类型的表达式 x 和一个类型 T,主要表达式 x.(T) 断言 x 不是 nil,并且存储在 x 中的值是类型 T
你的示例:
result["args"].(map[string]interface{})["foo"]

这意味着你的results映射与键"args"相关联的值是map[string]interface{}类型(另一个具有string键和任何值的映射)。而你想访问与键"foo"相关联的该映射元素。
如果你对输入的JSON格式一无所知,那么你必须使用通用的map[string]interface{}类型来处理它。如果你知道输入JSON的确切结构,你可以创建一个struct来匹配预期的字段,这样你就可以将JSON文本解组为你自定义的struct类型的值,例如:
type Point struct {
    Name string
    X, Y int
}

func main() {
    in := `{"Name":"center","X":2,"Y":3}`

    pt := Point{}
    json.Unmarshal([]byte(in), &pt)

    fmt.Printf("Result: %+v", pt)
}

输出:

Result: {Name:center X:2 Y:3}

请在Go Playground上尝试一下。

对输入进行建模

您当前的JSON输入可以使用以下类型进行建模:

type Data struct {
    Args struct {
        Foo string
    }
}

访问 Foo(在Go Playground上尝试):

d := Data{}
json.Unmarshal([]byte(in), &d)
fmt.Println("Foo:", d.Args.Foo)

另外,如果 foointerface{} 类型,那么执行 string(foo)foo.(string) 有什么区别? - Sreejith Ramakrishnan
@SreejithRamakrishnan 我认为如果您使用自定义的“struct”,也是通过反射填充的,因此不会有任何显着的性能损失。 - icza
2
@SreejithRamakrishnan,是的,“string(foo)”和“foo.(string)”之间有区别。前者是一种_转换_,而后者是一种_类型断言_。类型断言只能用于_接口类型_(interface{}是一个空接口,符合条件),关于转换的规则请参阅规范:Conversions。在您的情况下,您只能使用类型断言而不能使用转换。 - icza

11

struct 是最好的选择,但如果你坚持,你可以为 map 添加一个类型声明,然后添加方法来帮助进行类型断言:

package main
import "encoding/json"

type dict map[string]interface{}

func (d dict) d(k string) dict {
   return d[k].(map[string]interface{})
}

func (d dict) s(k string) string {
   return d[k].(string)
}

func main() {
   apiResponse := []byte(`{"args": {"foo": "bar"}}`)
   var result dict
   json.Unmarshal(apiResponse, &result)
   foo := result.d("args").s("foo")
   println(foo == "bar")
}

https://golang.org/ref/spec#Type_declarations


切片的辅助方法:func (d dict) a(k string) []interface{} { return d[k].([]interface{}) } - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接