在 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")
}
所以我正在尝试解析 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 typeT
, the primary expressionx.(T)
asserts thatx
is notnil
and that the value stored inx
is of typeT
.
你的例子:
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")
}