如何访问深层嵌套的JSON键和值

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

how to access deeply nested json keys and values

问题

我正在用Go语言编写一个WebSocket客户端。我从服务器接收到以下JSON数据:

{"args":[{"time":"2013-05-21 16:57:17"}],"name":"send:time"}

我试图访问time参数,但是无法理解如何深入到接口类型中:

package main;
import "encoding/json"
import "log"
func main() {
   msg := `{"args":[{"time":"2013-05-21 16:56:16", "tzs":[{"name":"GMT"}]}],"name":"send:time"}`
   u := map[string]interface{}{}
   err := json.Unmarshal([]byte(msg), &u)
   if err != nil {
       panic(err)
   }
   args := u["args"]
   log.Println(args[0]["time"])   // 无效的表示法...
}

这显然会报错,因为表示法不正确:

invalid operation: args[0] (index of type interface {})

我找不到一种方法来深入到map中获取嵌套的键和值。

一旦我能够获取动态值,我想声明这些消息。我应该如何编写一个类型结构来表示这样复杂的数据结构?

英文:

I'm writing a websocket client in Go. I'm receiving the following JSON from the server:

{"args":[{"time":"2013-05-21 16:57:17"}],"name":"send:time"}

I'm trying to access the time parameter, but just can't grasp how to reach deep into an interface type:

 package main;
 import "encoding/json"
 import "log"
 func main() {
    msg := `{"args":[{"time":"2013-05-21 16:56:16", "tzs":[{"name":"GMT"}]}],"name":"send:time"}`
    u := map[string]interface{}{}
    err := json.Unmarshal([]byte(msg), &u)
    if err != nil {
        panic(err)
    }
    args := u["args"]
    log.Println( args[0]["time"] )   // invalid notation...
}

Which obviously errors, since the notation is not right:

   invalid operation: args[0] (index of type interface {})

I just can't find a way to dig into the map to grab deeply nested keys and values.

Once I can get over grabbing dynamic values, I'd like to declare these messages. How would I write a type struct to represent such complex data structs?

答案1

得分: 10

你可以考虑使用包github.com/bitly/go-simplejson

查看文档:http://godoc.org/github.com/bitly/go-simplejson

示例:

time, err := json.Get("args").GetIndex(0).String("time")
if err != nil {
    panic(err)
}
log.Println(time)
英文:

You may like to consider the package github.com/bitly/go-simplejson

See the doc: http://godoc.org/github.com/bitly/go-simplejson

Example:

time, err := json.Get("args").GetIndex(0).String("time")
if err != nil {
    panic(err)
}
log.Println(time)

答案2

得分: 8

The interface{} 部分的 map[string]interface{} 你解码成的将会匹配该字段的类型。所以在这个例子中:

args.([]interface{})[0].(map[string]interface{})["time"].(string)

应该返回 2013-05-21 16:56:16

然而,如果你知道 JSON 的结构,你可以尝试定义一个与该结构匹配的结构体,并将其解码为该结构体。例如:

type Time struct {
    Time time.Time      `json:"time"`
    Timezone []TZStruct `json:"tzs"` // 显然,你还需要定义 TZStruct
    Name string         `json:"name"`
}

type TimeResponse struct {
    Args []Time         `json:"args"`
}

var t TimeResponse
json.Unmarshal(msg, &t)

这可能不是完美的,但应该能给你一个思路。

英文:

The interface{} part of the map[string]interface{} you decode into will match the type of that field. So in this case:

args.([]interface{})[0].(map[string]interface{})["time"].(string)

should return "2013-05-21 16:56:16"

However, if you know the structure of the JSON, you should try defining a struct that matches that structure and unmarshal into that. Ex:

type Time struct {
    Time time.Time      `json:"time"`
    Timezone []TZStruct `json:"tzs"` // obv. you need to define TZStruct as well
    Name string         `json:"name"`
}

type TimeResponse struct {
    Args []Time         `json:"args"`
}

var t TimeResponse
json.Unmarshal(msg, &t)

That may not be perfect, but should give you the idea

答案3

得分: 1

我对Golang非常陌生,之前是用Python的,一直在处理编码/解码JSON方面遇到困难。我在https://github.com/tidwall/gjson找到了gjson,它对我帮助很大:

package main

import "github.com/tidwall/gjson"

func main() {
    msg := (`{"args":[{"time":"2013-05-21 16:56:16", "tzs":[{"name":"GMT"}]}],"name":"send:time"}`)
    value := gjson.Get(msg, "args.#.time")
    println(value.String())
}

["2013-05-21 16:56:16"]

此外,我注意到了如何转换为结构体的注释:

package main

import (
    "encoding/json"
    "fmt"
)

type msgFormat struct {
    Time string       `json:"time"`
    Tzs  msgFormatTzs `json:"tzs"`
    Name string       `json:"name"`
}

type msgFormatTzs struct {
    TzsName string `json:"name"`
}


func main() {

    msg := (`{"args":[{"time":"2013-05-21 16:56:16", "tzs":[{"name":"GMT"}]}],"name":"send:time"}`)

    r, err := json.Marshal(msgFormatTzs{msg})

    if err != nil {
        panic(err)
    }

    fmt.Printf("%v", r)
}

Go playground上尝试一下。

英文:

I'm extremely new to Golang coming from Python, and have always struggled with encode/decoding json. I found gjson at https://github.com/tidwall/gjson, and it helped me immensely:

package main
    
import "github.com/tidwall/gjson"

func main() {
	msg := (`{"args":[{"time":"2013-05-21 16:56:16", "tzs":[{"name":"GMT"}]}],"name":"send:time"}`)
	value := gjson.Get(msg, "args.#.time")
	println(value.String())
}
-----------------------
["2013-05-21 16:56:16"]

Additionally, I noticed the comment of how to convert into Struct

package main
    
import (
    	"encoding/json"
    	"fmt"
    )

type msgFormat struct {
	Time string       `json:"time"`
	Tzs  msgFormatTzs `json:"tzs"`
	Name string       `json:"name"`
}

type msgFormatTzs struct {
	TzsName string `json:"name"`
}


func main() {

	msg := (`{"args":[{"time":"2013-05-21 16:56:16", "tzs":[{"name":"GMT"}]}],"name":"send:time"}`)

	r, err := json.Marshal(msgFormatTzs{msg})

	if err != nil {
		panic(err)
	}

	fmt.Printf("%v", r)
}

Try on Go playground

huangapple
  • 本文由 发表于 2013年5月21日 23:42:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/16674059.html
匿名

发表评论

匿名网友

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

确定