Golang如何处理具有动态相关键的JSON数据?

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

Golang consume json with dynamic relevant keys

问题

我是GO的新手,我正在尝试使用GO从各种API中获取JSON数据,并将它们放入结构体中。其中一个结构体的数据格式如下:

  1. {"MS": {
  2. "last":"25",
  3. "highestBid":"20"},
  4. "GE": {
  5. "last": "24",
  6. "highestBid": "22"}
  7. }

虽然我可以找到关于使用动态键进行消费的信息,但我找到的所有示例都将最外层的键视为任意和无关紧要的。我需要将其作为键值对使用,如下所示:

  1. {"MarketName": "GE", "last":"24","highestBid":"22"}

我了解使用接口映射,但我无法弄清楚如何将动态键映射到结构体中的键值对。我在playground上找到了一个示例代码,其中省略了需要的键。代码如下:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. var jsonBytes = []byte(`
  7. {"MS": {
  8. "last":"25",
  9. "highestBid":"20"},
  10. "GE": {
  11. "last": "24",
  12. "highestBid": "22"}
  13. }`)
  14. type Market struct {
  15. Last string
  16. HighestBid string
  17. }
  18. func main() {
  19. // Unmarshal using a generic interface
  20. var f interface{}
  21. err := json.Unmarshal(jsonBytes, &f)
  22. if err != nil {
  23. fmt.Println("Error parsing JSON: ", err)
  24. }
  25. fmt.Println(f)
  26. }

目前它的输出是:

  1. map[MS:map[last:25 highestBid:20] GE:map[highestBid:22 last:24]]

正如我所说,我是GO的新手,我非常感谢任何帮助和解释。

英文:

I am new to GO and I am trying to consume json data from a variety of API's using GO and place them in struct's one of them Formats the data like so

  1. {"MS": {
  2. "last":"25",
  3. "highestBid":"20"},
  4. "GE": {
  5. "last": "24",
  6. "highestBid": "22"}
  7. }

While I can find information on Consuming with dynamic keys, all the examples I found throw away the Outer most key as arbitrary and irrelevant. I need to use it as a key value pair like bellow:

  1. {"MarketName": "GE", "last":"24","higestBid":"22"}

I understand Using Interface map but I cant figure out how to map the dynamic key to the struct as a key : value pair like above. My Code example to map leaving out the need key can be found at play ground Relevant Code

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. var jsonBytes = []byte(`
  7. {"MS": {
  8. "last":"25",
  9. "highestBid":"20"},
  10. "GE": {
  11. "last": "24",
  12. "highestBid": "22"}
  13. }`)
  14. type Market struct {
  15. Last string
  16. HighestBid string
  17. }
  18. func main() {
  19. // Unmarshal using a generic interface
  20. var f interface{}
  21. err := json.Unmarshal(jsonBytes, &f)
  22. if err != nil {
  23. fmt.Println("Error parsing JSON: ", err)
  24. }
  25. fmt.Println(f)
  26. }

as it stands it outputs

  1. map[MS:map[last:25 highestBid:20] GE:map[highestBid:22 last:24]]

As I stated I am new to GO and as much help and explanation that i can get would be very appreciated

答案1

得分: 0

你已经完成了一半的工作,只需要将数据解组到你的结构体中,然后稍微处理一下数据:

  1. type Market struct {
  2. Name string
  3. Last string
  4. HighestBid string
  5. }
  6. func main() {
  7. // 使用通用接口进行解组
  8. var f map[string]Market
  9. err := json.Unmarshal(jsonBytes, &f)
  10. if err != nil {
  11. fmt.Println("解析JSON时出错:", err)
  12. return
  13. }
  14. markets := make([]Market, 0, len(f))
  15. for k, v := range f {
  16. v.Name = k
  17. markets = append(markets, v)
  18. }
  19. fmt.Println(markets)
  20. }

这里有一个可工作的示例:https://play.golang.org/p/iagx8RWFfx_k

英文:

You're halfway there already, you just need to unmarshal into your struct and then massage the data a little:

  1. type Market struct {
  2. Name string
  3. Last string
  4. HighestBid string
  5. }
  6. func main() {
  7. // Unmarshal using a generic interface
  8. var f map[string]Market
  9. err := json.Unmarshal(jsonBytes, &f)
  10. if err != nil {
  11. fmt.Println("Error parsing JSON: ", err)
  12. return
  13. }
  14. markets := make([]Market, 0, len(f))
  15. for k,v := range f {
  16. v.Name = k
  17. markets = append(markets,v)
  18. }
  19. fmt.Println(markets)
  20. }

Working example here: https://play.golang.org/p/iagx8RWFfx_k

答案2

得分: 0

如果Markets的一个切片是对你有用的数据结构,你可能希望给它取一个别名,并实现MarketList.UnmarshalJSON([]byte)方法,代码如下:

  1. type Market struct {
  2. MarketName string
  3. Last string
  4. HighestBid string
  5. }
  6. type MarketList []Market
  7. func (ml *MarketList) UnmarshalJSON(b []byte) error {
  8. tmp := map[string]Market{}
  9. err := json.Unmarshal(b, &tmp)
  10. if err != nil {
  11. return err
  12. }
  13. var l MarketList
  14. for k, v := range tmp {
  15. v.MarketName = k
  16. l = append(l, v)
  17. }
  18. *ml = l
  19. return nil
  20. }
  21. func main() {
  22. ml := MarketList{}
  23. // 直接解组为 []Market 别名
  24. _ = json.Unmarshal(jsonBytes, &ml)
  25. fmt.Printf("%+v\n", ml)
  26. }

可运行版本在这里

英文:

If a slice of Markets is a data structure that's going to be useful to you, you might wish to alias it and implement MarketList.UnmarshalJSON([]byte), like so:

  1. type Market struct {
  2. MarketName string
  3. Last string
  4. HighestBid string
  5. }
  6. type MarketList []Market
  7. func (ml *MarketList) UnmarshalJSON(b []byte) error {
  8. tmp := map[string]Market{}
  9. err := json.Unmarshal(b, &tmp)
  10. if err != nil {
  11. return err
  12. }
  13. var l MarketList
  14. for k, v := range tmp {
  15. v.MarketName = k
  16. l = append(l, v)
  17. }
  18. *ml = l
  19. return nil
  20. }
  21. func main() {
  22. ml := MarketList{}
  23. // Unmarshal directly into a []Market alias
  24. _ = json.Unmarshal(jsonBytes, &ml)
  25. fmt.Printf("%+v\n", ml)
  26. }

Runnable version here.

huangapple
  • 本文由 发表于 2018年1月24日 06:10:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/48411657.html
匿名

发表评论

匿名网友

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

确定