Reputation: 1382
So I'm trying to parse a JSON response. 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:
result["args"].(map[string]interface{})["foo"]
Here, what is the .()
notation? Is this correct?
Upvotes: 39
Views: 61347
Reputation: 1
struct
is the best option, but if you insist, you can add a type declaration for a map, then you can add methods to help
with the type assertions:
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
Upvotes: 12
Reputation: 417512
The notation x.(T)
is called a 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
.
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). And you want to access the element of that map associated with the key "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. 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:
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.
Your current JSON input could be modelled with this type:
type Data struct {
Args struct {
Foo string
}
}
And accessing Foo
(try it on the Go Playground):
d := Data{}
json.Unmarshal([]byte(in), &d)
fmt.Println("Foo:", d.Args.Foo)
Upvotes: 60