简体   繁体   English

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

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

So I'm trying to parse a JSON response.所以我正在尝试解析 JSON 响应。 It can be multiple levels deep.它可以是多层次的深度。 This is what I did:这就是我所做的:

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

Firstly, is this the right way to do it?首先,这是正确的做法吗?

Lets say the response was as follows:可以说响应如下:

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

To access key foo , I saw a playground doing this:要访问密钥foo ,我看到一个操场这样做:

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

Here, what is the .() notation?这里, .()符号是什么? Is this correct?这样对吗?

The notation x.(T) is called a Type Assertion .符号x.(T)称为类型断言

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 .为表达式x接口类型的,并且一个类型T ,初级表达式x.(T)声称, x是不nil ,并且存储在值x的类型为T

Your example:你的例子:

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

It means that the value of your results map associated with key "args" is of type map[string]interface{} (another map with string keys and any values).这意味着与键"args"关联的results映射的值是map[string]interface{} (另一个带有string键和任何值的映射)。 And you want to access the element of that map associated with the key "foo" .并且您想访问与键"foo"关联的该映射的元素。

If you know noting about the input JSON format, then yes, you have to use a generic map[string]interface{} type to process it.如果您知道输入 JSON 格式,那么是的,您必须使用通用的map[string]interface{}类型来处理它。 If you know the exact structure of the input JSON, you can create a struct to match the expected fields, and doing so you can unmarshal a JSON text into a value of your custom struct type, for example:如果您知道输入 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)
}

Output:输出:

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

Try it on the Go Playground .Go Playground上试一试。

Modeling your input为您的输入建模

Your current JSON input could be modelled with this type:您当前的 JSON 输入可以使用以下类型建模:

type Data struct {
    Args struct {
        Foo string
    }
}

And accessing Foo (try it on the Go Playground) :并访问Foo (在Go Playground上尝试

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

I prefer to add a type declaration for a Map, then you can add methods to help with the type assertions:我更喜欢为 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 https://golang.org/ref/spec#Type_declarations

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM