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

Accessing Nested Map of Type map[string]interface{} in Golang

所以我正在尝试解析 JSON 响应。它可以是多层次的深度。这就是我所做的:

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

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

假设响应如下:

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

要访问密钥 foo,我看到一个 playground 这样做:

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

这里,.()是什么表示法?这是正确的吗?

符号 x.(T) 称为 Type Assertion

For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T.

你的例子:

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

这意味着与键 "args" 关联的 results 映射的值是 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)

struct是最好的选择,但如果你坚持,你可以为地图添加类型声明,然后你可以添加方法来帮助 使用类型断言:

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