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

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

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 :

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

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:

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"`
}

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

使用地图:

type Item struct {
    Name string `json:"name"`
    Success bool `json:"success"`
} 
type Response struct {
    Data map[string]Item `json:"data"`
}

在 playground 上运行它

英文:

Use a map:

type Item struct {
    Name string `json:"name"`
    Success bool `json:"success"`
} 
type Response struct {
    Data map[string]Item `json:"data"`
}

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

答案2

得分: 0

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

test.json

{
 "data": {
  "1018089108070373346": {
    "name": "一个不错的酒店",
    "success": true
   },
  "2017089208070373346": {
    "name": "另一个不错的酒店",
    "success": true
   }
  }
}

test.go

package main

import (
	"encoding/json"
	"fmt"
	"os"
)

// Item 结构体
type Item struct {
	Name    string `json:"name"`
	Success bool   `json:"success"`
}

// Response 结构体
type Response struct {
	Data map[string]Item `json:"data"`
}

func main() {
	jsonFile, err := os.Open("test.json")
	if err != nil {
		fmt.Println("打开测试文件时出错\n", err.Error())
		return
	}

	jsonParser := json.NewDecoder(jsonFile)
	var filedata Response
	if err = jsonParser.Decode(&filedata); err != nil {
		fmt.Println("读取测试文件时出错\n", err.Error())
		return
	}

	for key, value := range filedata.Data {
		fmt.Println(key, value.Name, value.Success)
	}
}

输出结果为:

1018089108070373346 一个不错的酒店 true
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

{
 &quot;data&quot;: {
  &quot;1018089108070373346&quot;: {
    &quot;name&quot;: &quot;A Nice Hotel&quot;,
    &quot;success&quot;: true
   },
  &quot;2017089208070373346&quot;: {
    &quot;name&quot;: &quot;Another Nice Hotel&quot;,
    &quot;success&quot;: true
   }
  }
}

test.go

package main

import (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;os&quot;
)

// Item struct
type Item struct {
	Name    string `json:&quot;name&quot;`
	Success bool   `json:&quot;success&quot;`
}

// Response struct
type Response struct {
	Data map[string]Item `json:&quot;data&quot;`
}

func main() {
	jsonFile, err := os.Open(&quot;test.json&quot;)
	if err != nil {
		fmt.Println(&quot;Error opening test file\n&quot;, err.Error())
		return
	}

	jsonParser := json.NewDecoder(jsonFile)
	var filedata Response
	if err = jsonParser.Decode(&amp;filedata); err != nil {
		fmt.Println(&quot;Error while reading test file.\n&quot;, err.Error())
		return
	}

	for key, value := range filedata.Data {
		fmt.Println(key, value.Name, value.Success)
	}
}

Which outputs:

1018089108070373346 A Nice Hotel true
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:

确定