在Golang中访问Type map [string] interface {}的嵌套Map

时间:2015-03-02 10:00:54

标签: json dictionary go interface

所以我试图解析JSON响应。它可以是多层次的。这就是我所做的:

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

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

让我们说回应如下:

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

要访问密钥foo,我看到playground执行此操作:

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

这里,.()符号是什么?这是对的吗?

2 个答案:

答案 0 :(得分:18)

符号x.(T)称为Type Assertion

  

对于接口类型的表达式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)

答案 1 :(得分:1)

我更喜欢为 Map 添加类型声明,然后您可以添加方法来帮助 使用类型断言:

package main
import "encoding/json"

type dict map[string]interface{}

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

func (d dict) S(s string) string {
   return d[s].(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