遍历 Golang Map

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

Traversing a Golang Map

问题

我初始化了一个名为data的变量,如下所示:

   var data interface{}

然后我将原始的JSON解组成了它。

   err = json.Unmarshal(raw, &data)

我对它运行了这两个函数:

   fmt.Println(reflect.TypeOf(data))
   fmt.Println(data)

它们返回了以下结果:

   map[string]interface {}
   map[tasks:[map[payload:map[key:36A6D454-FEEE-46EB-9D64-A85ABEABBCB7] code_name:image_resize]]]

我需要访问"key"。我尝试了以下方法和其他几种方法:

   data["tasks"][0]["payload"]["key"]
   data[0][0][0][0]

这些方法都给我返回了类似这样的错误:

    ./resize.go:44: invalid operation: data["tasks"] (index of type interface {})

有关如何从这个接口中获取"key"值的建议吗?提前感谢。

英文:

I initialized a variable named data like this:

   var data interface{}

Then I unmarshalled raw json into.

   err = json.Unmarshal(raw, &data)

I've run these two functions on it:

   fmt.Println(reflect.TypeOf(data))
   fmt.Println(data)

and those return this:

   map[string]interface {}
   map[tasks:[map[payload:map[key:36A6D454-FEEE-46EB-9D64-A85ABEABBCB7] code_name:image_resize]]]

and I need to access the "key". I have tried these approaches and a few more:

   data["tasks"][0]["payload"]["key"]
   data[0][0][0][0]

Those have all given me an error similar to this one:

    ./resize.go:44: invalid operation: data["tasks"] (index of type interface {})

Any advice on how to grab the "key" value out of this interface? Thanks in advance.

答案1

得分: 10

由于您已经了解您的模式,最好的方法是直接将其解组为您可以使用的结构。

package main

import (
	"encoding/json"
	"fmt"
)

type msg struct {
	Tasks []task `json:"tasks"`
}

type task struct {
	CodeName string  `json:"code_name"`
	Payload  payload `json:"payload"`
}

type payload struct {
	Key string `json:"key"`
}

func main() {
	var data msg
	raw := `{ "tasks": [ { "code_name": "image_resize", "payload": { "key": "36A6D454-FEEE-46EB-9D64-A85ABEABBCB7" } } ] }`

	err := json.Unmarshal([]byte(raw), &data)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(data.Tasks[0].Payload.Key)
}

如果您坚持使用原始代码的方式,您需要进行类型断言。我强烈建议在可能的情况下避免这种方式。这并不好玩。每一步都需要检查以确保它与您期望的数据结构匹配。

if m, ok := data.(map[string]interface{}); ok {
	if a, ok := m["tasks"].([]interface{}); ok && len(a) > 0 {
		if e, ok := a[0].(map[string]interface{}); ok {
			if p, ok := e["payload"].(map[string]interface{}); ok {
				if k, ok := p["key"].(string); ok {
					fmt.Println("The key is:", k)
				}
			}
		}
	}
}

回答Goodwine的问题:您可以通过阅读encoding/json的godoc来了解有关如何编组和解组的更多信息。我建议从这里开始:

英文:

Since you already know your schema, the best way to do this is to unmarshal directly into structs you can use.

http://play.golang.org/p/aInZp8IZQA

package main

import (
	"encoding/json"
	"fmt"
)

type msg struct {
	Tasks []task `json:"tasks"`
}

type task struct {
	CodeName string  `json:"code_name"`
	Payload  payload `json:"payload"`
}

type payload struct {
	Key string `json:"key"`
}

func main() {
	var data msg
	raw := `{ "tasks": [ { "code_name": "image_resize", "payload": { "key": "36A6D454-FEEE-46EB-9D64-A85ABEABBCB7" } } ] }`

	err := json.Unmarshal([]byte(raw), &data)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(data.Tasks[0].Payload.Key)
}

If you insist on doing things the hard way using your original code, you need to do type assertions. I highly recommend avoiding this route when possible. It is not fun. Every step needs to be checked to ensure it matches the data structure you expect.

http://play.golang.org/p/fI5sqKV19J

if m, ok := data.(map[string]interface{}); ok {
	if a, ok := m["tasks"].([]interface{}); ok && len(a) > 0 {
		if e, ok := a[0].(map[string]interface{}); ok {
			if p, ok := e["payload"].(map[string]interface{}); ok {
				if k, ok := p["key"].(string); ok {
					fmt.Println("The key is:", k)
				}
			}
		}
	}
}

In response to Goodwine's question: You can read further about how to marshal and unmarshal by reading the encoding/json godoc. I suggest starting here:

答案2

得分: 1

另一种解决方案是使用第三方包,比如https://github.com/Jeffail/gabs。

使用gabs,上面@stephen-weinberg的示例可以写成:

raw := `{ "tasks": [ { "code_name": "image_resize", "payload": { "key": "36A6D454-FEEE-46EB-9D64-A85ABEABBCB7" } } ] }`
j, _ := gabs.ParseJSON([]byte(raw))

fmt.Println("The key is", j.S("tasks").Index(0).S("payload", "key").Data().(string))

我还遇到了其他流行的处理JSON的包,比如https://github.com/bitly/go-simplejson和https://github.com/antonholmquist/jason。

英文:

Another solution is to use 3rd-party package like https://github.com/Jeffail/gabs

With gabs, The example above by @stephen-weinberg can be written as:

raw := `{ "tasks": [ { "code_name": "image_resize", "payload": { "key": "36A6D454-FEEE-46EB-9D64-A85ABEABBCB7" } } ] }`
j, _ := gabs.ParseJSON([]byte(raw))

fmt.Println("The key is", j.S("tasks").Index(0).S("payload", "key").Data().(string))

other popular json handling packages I've stumbled upon are: https://github.com/bitly/go-simplejson and https://github.com/antonholmquist/jason.

huangapple
  • 本文由 发表于 2014年4月9日 23:25:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/22967149.html
匿名

发表评论

匿名网友

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

确定