3 回答
TA贡献1852条经验 获得超7个赞
请参阅此博客条目,该条目彻底涵盖了该主题,特别是解码任意数据部分。使用它你可以做这样的事情:(游乐场示例)
package main
import (
"encoding/json"
"fmt"
)
func main() {
// Creating the maps for JSON
m := map[string]interface{}{}
// Parsing/Unmarshalling JSON encoding/json
err := json.Unmarshal([]byte(input), &m)
if err != nil {
panic(err)
}
parseMap(m)
}
func parseMap(aMap map[string]interface{}) {
for key, val := range aMap {
switch concreteVal := val.(type) {
case map[string]interface{}:
fmt.Println(key)
parseMap(val.(map[string]interface{}))
case []interface{}:
fmt.Println(key)
parseArray(val.([]interface{}))
default:
fmt.Println(key, ":", concreteVal)
}
}
}
func parseArray(anArray []interface{}) {
for i, val := range anArray {
switch concreteVal := val.(type) {
case map[string]interface{}:
fmt.Println("Index:", i)
parseMap(val.(map[string]interface{}))
case []interface{}:
fmt.Println("Index:", i)
parseArray(val.([]interface{}))
default:
fmt.Println("Index", i, ":", concreteVal)
}
}
}
const input = `
{
"outterJSON": {
"innerJSON1": {
"value1": 10,
"value2": 22,
"InnerInnerArray": [ "test1" , "test2"],
"InnerInnerJSONArray": [{"fld1" : "val1"} , {"fld2" : "val2"}]
},
"InnerJSON2":"NoneValue"
}
}
`
这将打印:
//outterJSON
//innerJSON1
//InnerInnerJSONArray
//Index: 0
//fld1 : val1
//Index: 1
//fld2 : val2
//value1 : 10
//value2 : 22
//InnerInnerArray
//Index 0 : test1
//Index 1 : test2
//InnerJSON2 : NoneValue
关键是在处理接口类型时必须使用类型断言。类型开关可以根据需要轻松确定类型。该代码将递归地遍历任何嵌套数组或映射,因此您可以根据需要添加任意数量的级别并获取所有值。
TA贡献1828条经验 获得超13个赞
这里和这里有相关的问题(可能还有其他问题)。
有一些更复杂的 JSON 解析 API 可以让您的工作更轻松。一个例子是stretchr/objx。
一个使用 objx 的例子:
document, err := objx.FromJSON(json)
// TODO handle err
document.Get("path.to.field[0].you.want").Str()
当您真的不知道 JSON 结构是什么时,这会起作用。但是,如果您提前知道 JSON 输入的结构,则首选方法是使用结构来描述它并使用标准 API 进行编组。
TA贡献1835条经验 获得超7个赞
您需要解析 JSON,然后通过结构递归检查所包含值的类型并以某种方式处理它们。
下面的示例函数接受一个*interface{}(指向任何类型的指针)和一个字符串、整数和对象指针的处理函数,它产生它发现的项目:
func eachJsonValue(obj *interface{}, handler func(*string, *int, *interface{})) {
if obj == nil {
return
}
// Yield all key/value pairs for objects.
o, isObject := (*obj).(map[string]interface{})
if isObject {
for k, v := range o {
handler(&k, nil, &v)
eachJsonValue(&v, handler)
}
}
// Yield each index/value for arrays.
a, isArray := (*obj).([]interface{})
if isArray {
for i, x := range a {
handler(nil, &i, &x)
eachJsonValue(&x, handler)
}
}
// Do nothing for primitives since the handler got them.
}
如下所示调用它会打印列出的结果。当然,您的处理程序函数可以对已知的键/值(例如“fld1”)执行一些特殊操作:
func main() {
// Parse the JSON.
var obj interface{}
json.Unmarshal([]byte(input), &obj) // XXX: check the error value.
// Handle object key/value pairs and array index/items.
eachJsonValue(&obj, func(key *string, index *int, value *interface{}) {
if key != nil { // It's an object key/value pair...
fmt.Printf("OBJ: key=%q, value=%#v\n", *key, *value)
} else { // It's an array item...
fmt.Printf("ARR: index=%d, value=%#v\n", *index, *value)
}
})
}
// OBJ: key="outterJSON", value=map[string]interface {}{...}
// OBJ: key="innerJSON1", value=map[string]interface {}{...}
// OBJ: key="value1", value=10
// OBJ: key="value2", value=22
// OBJ: key="InnerInnerArray", value=[]interface {}{...}
// ARR: index=0, value="test1"
// ARR: index=1, value="test2"
// OBJ: key="InnerInnerJSONArray", value=[]interface {}{...}
// ARR: index=0, value=map[string]interface {}{...}
// OBJ: key="fld1", value="val1"
// ARR: index=1, value=map[string]interface {}{...}
// OBJ: key="fld2", value="val2"
// OBJ: key="InnerJSON2", value="NoneValue"
- 3 回答
- 0 关注
- 185 浏览
添加回答
举报