【问题标题】:How to get values from list nested within list in JSON如何从嵌套在JSON列表中的列表中获取值
【发布时间】:2021-11-25 22:45:54
【问题描述】:

我有一个 JSON 结构,例如:

    {
       "persons":[
          {
             "name":"mark",
             "surname":"zuckerberg",
             "data":[
                {
                   "userid":"09210",
                   "username":"mark290",
                   "registered_date":"10-01-2017"
                },

                {
                   "userid":"092240",
                   "username":"mark291",
                   "registered_date":"11-01-2017"
                }
             ]
          },

          {
             "name":"bill",
             "surname":"clinton",
             "data":[
                {
                   "userid":"0442340",
                   "username":"billy",
                   "registered_date":"10-01-2000"
                },

                {
                   "userid":"89472894",
                   "username":"billary",
                   "registered_date":"11-01-2015"
                }
             ]
          }
       ]
    }

我需要获取每个人的每个用户名。 目前,在我完全是新手的 Go 中,我只能使用这个 sn-p 获取“数据”中的单个 JSONS:

    j := []byte(data)
    var f interface{}
    err := json.Unmarshal(j, &f)
    map := f.(map[string]interface{})
    for _,item := range map["persons"].([]interface{}) {
        fmt.Printf("%v", item.(map[string]interface{})["data"])
    fmt.Println(err)

我很难理解如何深入数据中的每个 JSON 结构以获得每个键值对。

【问题讨论】:

  • 考虑使用具体类型而不是interface{}
  • 声明一个与你的数据结构相匹配的 Go 类型。解组为该类型的值。见example
  • 但我忘了提到,在我的例子中,JSON 结构并不总是相同的。这是不一致的。我认为在这种情况下最好使用接口而不是结构。
  • github.com/mitchellh/mapstructure "数据格式不一致" 几乎是 mapstructure 的准确定位。仅使用接口和映射的问题是您必须检查所有类型。结构 ummarshalling 为您处理。

标签: json go


【解决方案1】:

您可以将JSON字节对应的精确嵌套结构定义为Unmarshal

package main

import (
    "encoding/json"
    "fmt"
)

type Trunk struct {
    Persons []Person `json:"persons"`
}

type Person struct {
    Name    string `json:"name"`
    Surname string `json:"surname"`
    Data    []User `json:"data"`
}

type User struct {
    Userid          string `json:"userid"`
    Username        string `json:"username"`
    Registered_date string `json:"registered_date"`
}

func main() {
    rawstring := []byte(`
    {
       "persons":[
          {
             "name":"mark",
             "surname":"zuckerberg",
             "data":[
                {
                   "userid":"09210",
                   "username":"mark290",
                   "registered_date":"10-01-2017"
                },

                {
                   "userid":"092240",
                   "username":"mark291",
                   "registered_date":"11-01-2017"
                }
             ]
          },

          {
             "name":"bill",
             "surname":"clinton",
             "data":[
                {
                   "userid":"0442340",
                   "username":"billy",
                   "registered_date":"10-01-2000"
                },

                {
                   "userid":"89472894",
                   "username":"billary",
                   "registered_date":"11-01-2015"
                }
             ]
          }
       ]
    }
    `)

    jsondata := Trunk{}
    if err := json.Unmarshal(rawstring, &jsondata); err == nil {
        fmt.Println(jsondata)

        // print first username of first person
        // fmt.Println(jsondata.Persons[0].Data[0].Username)
        // print each username of each person
        for _, person := range jsondata.Persons {
            for _, d := range person.Data {
                fmt.Println(d.Username)
            }
        }
    } else {
        fmt.Println("Unmarshal failed!")
    }
}

或者使用更紧凑的结构定义:

type Trunk struct {
    Persons []struct {
        Name    string `json:"name"`
        Surname string `json:"surname"`
        Data    []struct {
            Userid          string `json:"userid"`
            Username        string `json:"username"`
            Registered_date string `json:"registered_date"`
        } `json:"data"`
    } `json:"persons"`
}

【讨论】:

    【解决方案2】:

    如果您想使用流媒体方法,您可以尝试Decoder 查找“用户名”Token 并获取下一个带有“值”的Token

    dec := json.NewDecoder(strings.NewReader(rawstring))
    for {
        t, err := dec.Token()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }
        if val, ok := t.(string); ok && val == "username" {
            t, err := dec.Token()
            if err == io.EOF {
                break
            }
            fmt.Println(t)
        }
    }
    

    PLAYGROUND

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-12
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 2020-02-18
      相关资源
      最近更新 更多