golang:快速访问嵌套的map中的数据

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

golang: quickly access data of maps within maps

问题

{
"service": {
"auth": {
"token": {
"$t": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}

英文:

So I've got the following bit of JSON and I want to pull out the "$t" value under "token". Continue for Go code...

{
  "@encoding": "iso-8859-1",
  "@version": "1.0",
  "service": {
    "auth": {
      "expiresString": {
        "$t": "2013-06-12T01:15:28Z"
      },
      "token": {
        "$t": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      },
      "expires": {
        "$t": "1370999728"
      },
      "key": {
        "$t": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
}

I have the following snippet of Go code that unmarshals the json into an interface. Then I work my way down to the "$t" value of "token". This approach does work, but it's ugly.

My question: is there a faster way to access that value than by converting each map into an interface? I'm very new to Go and am not aware of many of the useful features of interfaces and maps.

var f interface{}
jerr := json.Unmarshal(body, &f)
m := f.(map[string]interface{})
ser := m["service"].(map[string]interface{})
a := ser["auth"].(map[string]interface{})
tok := a["token"].(map[string]interface{})
token := tok["$t"]
fmt.Fprintf(w, "Token: %v\n", token)

Thanks in advance!

答案1

得分: 12

如果这是你想要的唯一值,那么你可以使用一个匿名的struct来定义数据的路径。

var m = new(struct{Service struct{Auth struct{Token map[string]string}}})

var err = json.Unmarshal([]byte(data), &m)

fmt.Println(m.Service.Auth.Token["$t"], err)

DEMO: http://play.golang.org/p/ZdKTzM5i57


如果不想使用map作为最内层的数据,我们可以使用另一个struct,但是我们需要提供一个字段标签来别名化名称。

var m = new(struct{Service struct{Auth struct{Token struct{T string `json:"$t"`}}}})

var err = json.Unmarshal([]byte(data), &m)

fmt.Println(m.Service.Auth.Token.T, err)

DEMO: http://play.golang.org/p/NQTpaUvanx

英文:

If that's the only value you want, then how about using an anonymous struct that defines the path to your data.

var m = new(struct{Service struct{Auth struct{Token map[string]string}}})

var err = json.Unmarshal([]byte(data), &m)

fmt.Println(m.Service.Auth.Token["$t"], err)

DEMO: http://play.golang.org/p/ZdKTzM5i57


Instead of using a map for the innermost data, we could use another struct, but we'd need to provide a field tag to alias the name.

var m = new(struct{Service struct{Auth struct{Token struct{T string `json:"$t"`}}}})

var err = json.Unmarshal([]byte(data), &m)

fmt.Println(m.Service.Auth.Token.T, err)

DEMO: http://play.golang.org/p/NQTpaUvanx

答案2

得分: 7

你可以使用我们的stew包中的objects.Map,它为地图提供了点访问器:

objects.Map(data).Get("service.auth.token")

请参阅http://godoc.org/github.com/stretchr/stew/objects

英文:

OR you can use objects.Map from our stew package, it gives you dot accessors for maps:

objects.Map(data).Get("service.auth.token")

see http://godoc.org/github.com/stretchr/stew/objects

huangapple
  • 本文由 发表于 2013年6月12日 08:43:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/17056044.html
匿名

发表评论

匿名网友

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

确定