将由 REST API 返回的包含动态键的 JSON 映射到 Golang 中的结构体。

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

Mapping JSON returned by REST API containing dynamic keys to a struct in Golang

问题

我正在从我的Go程序中调用一个REST API,该API在请求中接收n个酒店ID,并将它们的数据作为JSON返回。当我在请求中传递2个ID(1018089108070373346和2017089208070373346)时,响应如下所示:

{
"data": {
"1018089108070373346": {
"name": "A Nice Hotel",
"success": true
},
"2017089208070373346": {
"name": "Another Nice Hotel",
"success": true
}
}
}

由于我对Golang还不熟悉,我使用了一个可在http://mholt.github.io/json-to-go/上找到的JSON转Go结构体的工具来获取上述响应的结构体表示。我得到的结果是:

type Autogenerated struct {
Data struct {
Num1017089108070373346 struct {
Name string json:"name"
Success bool json:"success"
} json:"1017089108070373346"
Num2017089208070373346 struct {
Name string json:"name"
Success bool json:"success"
} json:"2017089208070373346"
} json:"data"
}

我不能使用上述结构体,因为实际的ID值和我传递的ID数量每次可能都不同,返回的JSON将具有不同的键。如何将这种情况映射到一个结构体中呢?

谢谢。

英文:

I'm calling a REST API from my Go program which takes n number of hotel ids in the request and returns their data as a JSON. The response is like the following when say I pass 2 ids in the request, 1018089108070373346 and 2017089208070373346 :

  1. {
  2. "data": {
  3. "1018089108070373346": {
  4. "name": "A Nice Hotel",
  5. "success": true
  6. },
  7. "2017089208070373346": {
  8. "name": "Another Nice Hotel",
  9. "success": true
  10. }
  11. }
  12. }

Since I'm new to Golang I using a JSON Go tool available at http://mholt.github.io/json-to-go/ to get the struct representation for the above response. What I get is:

  1. type Autogenerated struct {
  2. Data struct {
  3. Num1017089108070373346 struct {
  4. Name string `json:"name"`
  5. Success bool `json:"success"`
  6. } `json:"1017089108070373346"`
  7. Num2017089208070373346 struct {
  8. Name string `json:"name"`
  9. Success bool `json:"success"`
  10. } `json:"2017089208070373346"`
  11. } `json:"data"`
  12. }

I cannot use the above struct because the actual id values and the number of ids I pass can be different each time, the JSON returned will have different keys. How can this situation be mapped to a struct ?

Thanks

答案1

得分: 3

使用地图:

  1. type Item struct {
  2. Name string `json:"name"`
  3. Success bool `json:"success"`
  4. }
  5. type Response struct {
  6. Data map[string]Item `json:"data"`
  7. }

在 playground 上运行它

英文:

Use a map:

  1. type Item struct {
  2. Name string `json:"name"`
  3. Success bool `json:"success"`
  4. }
  5. type Response struct {
  6. Data map[string]Item `json:"data"`
  7. }

<kbd>Run it on the playground</kbd>

答案2

得分: 0

以下是使用Mellow Marmots答案的示例代码,并展示了如何迭代响应中的项目。

test.json

  1. {
  2. "data": {
  3. "1018089108070373346": {
  4. "name": "一个不错的酒店",
  5. "success": true
  6. },
  7. "2017089208070373346": {
  8. "name": "另一个不错的酒店",
  9. "success": true
  10. }
  11. }
  12. }

test.go

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. )
  7. // Item 结构体
  8. type Item struct {
  9. Name string `json:"name"`
  10. Success bool `json:"success"`
  11. }
  12. // Response 结构体
  13. type Response struct {
  14. Data map[string]Item `json:"data"`
  15. }
  16. func main() {
  17. jsonFile, err := os.Open("test.json")
  18. if err != nil {
  19. fmt.Println("打开测试文件时出错\n", err.Error())
  20. return
  21. }
  22. jsonParser := json.NewDecoder(jsonFile)
  23. var filedata Response
  24. if err = jsonParser.Decode(&filedata); err != nil {
  25. fmt.Println("读取测试文件时出错\n", err.Error())
  26. return
  27. }
  28. for key, value := range filedata.Data {
  29. fmt.Println(key, value.Name, value.Success)
  30. }
  31. }

输出结果为:

  1. 1018089108070373346 一个不错的酒店 true
  2. 2017089208070373346 另一个不错的酒店 true
英文:

Here is some sample code that utilizes Mellow Marmots answer and shows how to iterate over the items in the response.

test.json

  1. {
  2. &quot;data&quot;: {
  3. &quot;1018089108070373346&quot;: {
  4. &quot;name&quot;: &quot;A Nice Hotel&quot;,
  5. &quot;success&quot;: true
  6. },
  7. &quot;2017089208070373346&quot;: {
  8. &quot;name&quot;: &quot;Another Nice Hotel&quot;,
  9. &quot;success&quot;: true
  10. }
  11. }
  12. }

test.go

  1. package main
  2. import (
  3. &quot;encoding/json&quot;
  4. &quot;fmt&quot;
  5. &quot;os&quot;
  6. )
  7. // Item struct
  8. type Item struct {
  9. Name string `json:&quot;name&quot;`
  10. Success bool `json:&quot;success&quot;`
  11. }
  12. // Response struct
  13. type Response struct {
  14. Data map[string]Item `json:&quot;data&quot;`
  15. }
  16. func main() {
  17. jsonFile, err := os.Open(&quot;test.json&quot;)
  18. if err != nil {
  19. fmt.Println(&quot;Error opening test file\n&quot;, err.Error())
  20. return
  21. }
  22. jsonParser := json.NewDecoder(jsonFile)
  23. var filedata Response
  24. if err = jsonParser.Decode(&amp;filedata); err != nil {
  25. fmt.Println(&quot;Error while reading test file.\n&quot;, err.Error())
  26. return
  27. }
  28. for key, value := range filedata.Data {
  29. fmt.Println(key, value.Name, value.Success)
  30. }
  31. }

Which outputs:

  1. 1018089108070373346 A Nice Hotel true
  2. 2017089208070373346 Another Nice Hotel true

huangapple
  • 本文由 发表于 2016年2月1日 10:18:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/35122105.html
匿名

发表评论

匿名网友

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

确定