请考虑以下代码:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func main() {
//Creating the maps for JSON
m := map[string]interface{}{}
//Parsing/Unmarshalling JSON encoding/json
err := json.Unmarshal([]byte(input), &m)
fmt.Println("\nReflect type of Parsing/Unmarshalling Error Object:\n",reflect.TypeOf(err))
fmt.Println("\nParsing/Unmarshalling Error Object:\n",err)
if err != nil {
panic(err)
}
fmt.Println("\nParsed JSON is as follows:\n",m)
fmt.Println("\nReflect type of parsed json object:\n", reflect.TypeOf(m))
for firstLvlkey, firstLvlValue := range m {
fmt.Println("First Level Key:", firstLvlkey)
fmt.Println("First Level Key reflect type of :", reflect.TypeOf(firstLvlkey))
fmt.Println("First Level Value:", firstLvlValue)
fmt.Println("First Level Value reflect type of :", reflect.TypeOf(firstLvlValue))
// <===============================>
//Here I want to iterate/loop over innerJSON1, InnerJSON2 then reach to level InnerInnerJSONArray - fld1 and fld2
// <===============================>
}
}
const input = `
{
"outterJSON":{
"innerJSON1":{
"value1":10,
"value2":22
,
"InnerInnerArray": [ "test1" , "test2"],
"InnerInnerJSONArray": [ {"fld1" : "val1"} , {"fld2" : "val2"} ]
},
"InnerJSON2":"NoneValue"
}
}
`
Run Code Online (Sandbox Code Playgroud)
我有一些要求,比如我想要读取/得到所有Key和值的String
类型进行一些处理adn我无法定义struct
因为我将获得动态JSON输入(例如InnerInnerArray
作为字符串然后第二级循环将给我索引数组和处理每个JSON都有密钥fld1
和val1
).
我希望迭代其中包含的每个键/值对,通过地图的最有效方法是什么?
注意:我是Go-lang的新手,您的建议/改进也是最受欢迎的.
Iam*_*NaN 20
请参阅此博客文章,其中详细介绍了此主题,特别是" 解码任意数据 "一节.使用它你可以做这样的事情:( 游乐场示例)
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"
}
}
`
Run Code Online (Sandbox Code Playgroud)
这将打印:
//outterJSON
//innerJSON1
//InnerInnerJSONArray
//Index: 0
//fld1 : val1
//Index: 1
//fld2 : val2
//value1 : 10
//value2 : 22
//InnerInnerArray
//Index 0 : test1
//Index 1 : test2
//InnerJSON2 : NoneValue
Run Code Online (Sandbox Code Playgroud)
关键是在使用接口类型时必须使用类型断言.类型开关可以根据需要轻松确定类型.代码将以递归方式遍历任何嵌套数组或映射,以便您可以添加任意数量的级别并获取所有值.
有一些更复杂的 JSON 解析 API 可以让您的工作变得更轻松。一个例子是stretchr/objx。
使用 objx 的示例:
document, err := objx.FromJSON(json)
// TODO handle err
document.Get("path.to.field[0].you.want").Str()
Run Code Online (Sandbox Code Playgroud)
当您确实不知道 JSON 结构是什么时,这会起作用。但是,如果您提前知道 JSON 输入的结构,则首选方法是使用结构来描述它并使用标准 API 进行编组。