英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论