I\'m in the infant stages of trying to wrap my mind around Go. At the moment, I\'m simulating an API request that returns a JSON-formatted string containing an array of objects.
The defaults that the json package will decode into when the type isn't declared are:
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
Since each record
is (in your example) a json object, you can assert each one as a map[string]interface{}
like so:
for _, record := range view {
log.Printf(" [===>] Record: %s", record)
if rec, ok := record.(map[string]interface{}); ok {
for key, val := range rec {
log.Printf(" [========>] %s = %s", key, val)
}
} else {
fmt.Printf("record not a map[string]interface{}: %v\n", record)
}
}
I prefer to declare my own Slice and Map, then I can add methods onto them to aid in the type assertions. I only included two methods below, but you can add more as needed:
package main
type Map map[string]interface{}
type Slice []interface{}
func (a Slice) M(n int) Map {
return a[n].(map[string]interface{})
}
func (m Map) N(s string) float64 {
return m[s].(float64)
}
Result:
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
response := strings.NewReader(`[
{"month": 12, "day": 31},
{"month": 11, "day": 30}
]`)
view := Slice{}
json.NewDecoder(response).Decode(&view)
for index := range view {
record := view.M(index)
for key := range record {
val := record.N(key)
fmt.Println(key, val)
}
}
}
https://golang.org/ref/spec#Type_declarations