在go lang中循环/遍历第二级嵌套JSON

Amo*_*rni 9 json go

请考虑以下代码:

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都有密钥fld1val1).

我希望迭代其中包含的每个键/值对,通过地图的最有效方法是什么?

注意:我是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)

关键是在使用接口类型时必须使用类型断言.类型开关可以根据需要轻松确定类型.代码将以递归方式遍历任何嵌套数组或映射,以便您可以添加任意数量的级别并获取所有值.


Ric*_*777 5

这里这里有相关的问题(可能还有其他问题)。

有一些更复杂的 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 进行编组。