为了账号安全,请及时绑定邮箱和手机立即绑定

在 go lang 中循环/迭代第二级嵌套 JSON

在 go lang 中循环/迭代第二级嵌套 JSON

Go
犯罪嫌疑人X 2021-09-27 15:47:05
考虑以下代码:package mainimport ("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"        }    }    `我有一些要求,比如我想读取/获取类型中的所有键和值以String进行某些处理,我无法定义,struct因为我将获得动态 JSON 输入(例如InnerInnerArray作为字符串,然后第二级循环会给我索引数组并处理每个具有键fld1和 的JSON val1。我希望遍历其中包含的每个键/值对,浏览地图的最有效方法是什么?注意:我是 Go-lang 的新手,也非常欢迎您对问题提出建议/改进。
查看完整描述

3 回答

?
慕姐4208626

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

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


查看完整回答
反对 回复 2021-09-27
?
慕田峪7331174

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 进行编组。


查看完整回答
反对 回复 2021-09-27
?
qq_花开花谢_0

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"


查看完整回答
反对 回复 2021-09-27
  • 3 回答
  • 0 关注
  • 185 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信