In go
the standard package encoding/json exposes json.Unmarshal
function to parse JSON.
It's possible to either unmarshal the JSON string in a predefined struct
, or use the interface{}
and iterate the result for unexpected JSON data structure.
That said, I can't parse complex JSON properly. Can someone tell me how to achieve this?
{
"k1" : "v1",
"k2" : "v2",
"k3" : 10,
"result" : [
[
["v4", v5, {"k11" : "v11", "k22" : "v22"}]
, ... ,
["v4", v5, {"k33" : "v33", "k44" : "v44"}
]
],
"v3"
]
}
json is read with the ioutil. ReadFile() function, which returns a byte slice that is decoded into the struct instance using the json. Unmarshal() function. At last, the struct instance member values are printed using for loop to demonstrate that the JSON file was decoded.
To parse JSON, we use the Unmarshal() function in package encoding/json to unpack or decode the data from JSON to a struct. Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. Note: If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.
To unmarshal a JSON array into a slice, Unmarshal resets the slice length to zero and then appends each element to the slice. As a special case, to unmarshal an empty JSON array into a slice, Unmarshal replaces the slice with a new empty slice.
Citing from JSON and Go:
Without knowing this data's structure, we can decode it into an interface{} value with Unmarshal:
b := []byte(`{
"k1" : "v1",
"k3" : 10,
result:["v4",12.3,{"k11" : "v11", "k22" : "v22"}]
}`)
var f interface{}
err := json.Unmarshal(b, &f)
At this point the Go value in f would be a map whose keys are strings and whose values are themselves stored as empty interface values:
f = map[string]interface{}{
"k1": "v1",
"k3": 10,
"result": []interface{}{
"v4",
12.3,
map[string]interface{}{
"k11":"v11",
"k22":"v22",
},
},
}
To access this data we can use a type assertion to access
f
's underlying map[string]interface{}:
m := f.(map[string]interface{})
We can then iterate through the map with a range statement and use a type switch to access its values as their concrete types:
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "is string", vv)
case int:
fmt.Println(k, "is int", vv)
case []interface{}:
fmt.Println(k, "is an array:")
for i, u := range vv {
fmt.Println(i, u)
}
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
}
In this way you can work with unknown JSON data while still enjoying the benefits of type safety.
More information about Go and JSON can be found in the original article. I changed the code snippets slightly to be more similar to the JSON in the question.
More recently, gjson offers selection of properties in JSON
k1 := gjson.Get(json, "k1")
k33 : = gjson.Get(json, "result.#.#.k33")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With