如何从JSON中嵌套的列表中获取值

huangapple go评论78阅读模式
英文:

How to get values from list nested within list in JSON

问题

我有一个类似于以下结构的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语言中,我只能获取"data"中的单个JSON,使用以下代码片段:

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

我很难理解如何深入"data"中的每个JSON结构,以获取每个键值对。

英文:

I have a JSON structure such as:

    {
       "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"
                }
             ]
          }
       ]
    }

I need to fetch each username for each person.
Currently, in Go, which I am a total newbie at, I can get only the single JSONS within "data", with this snippet:

    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)

I struggle to understand how to dive within each JSON struct within data in order to get each key,value pair.

答案1

得分: 3

你可以定义与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"`
}
英文:

You can define the accurate nested structure corresponding to the JSON bytes, to 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!")
	}
}

Or use a more compact structure defination:

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

得分: 1

如果你想使用流式处理方法,你可以尝试使用Decoder来查找"username" Token,并通过"value"获取下一个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

英文:

If you want to use streaming approach you can try to Decoder to find "username" Token and get next Token with "value".

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)
}
}

<kbd>PLAYGROUND</kbd>

huangapple
  • 本文由 发表于 2021年10月6日 00:27:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/69454107.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定