Currently, I try to parse JSON to map[string][]interface{}, but unmarshalling returns an error. According to (https://golang.org/pkg/encoding/json/), to unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:
- bool, for JSON booleans
- float64, for JSON numbers
- string, for JSON strings
-[]interface{}, for JSON arrays - map[string]interface{}, for JSON objects
- nil for JSON null
I wonder if golang is able to unmarshal map[string][]interface{}. The following is code snippet. I am new to Golang, thanks for help in advance.
// emailsStr looks like "{"isSchemaConforming":true,"schemaVersion":0,"unknown.0":[{"email_address":"test1@uber.com"},{"email_address":"test2@uber.com"}]}"
emailsRaw := make(map[string][]*entities.Email)
err := json.Unmarshal([]byte(emailsStr), &emailsRaw)
Error message:
&json.UnmarshalTypeError{Value:"number", Type:(*reflect.rtype)(0x151c7a0), Offset:44, Struct:"", Field:""}
Best Answer
The Go
encoding/json
package will only unmarshal dynamically to amap[string]interface{}
. From there, you will need to use type assertions and casting to pull out the values you want, like so:(https://play.golang.org/p/VEUEIwj3CIC)
Each time, Go's
.(<type>)
operator is used to assert and cast the dynamic value to a specific type. This particular code will panic if anything happens to be the wrong type at runtime, like if the contents ofunknown.0
aren't an array of JSON objects.The more idiomatic (and robust) way to do this in Go is to annotate a couple structs with
json:""
tags and haveencoding/json
unmarshal into them. This avoids all the nasty brittle.([]interface{})
type casting:(https://play.golang.org/p/iS6e0_87P2J)