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

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

问题描述:

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

我正在从Go程序中调用REST API,该程序需要 n em>个酒店 请求中的id,并以JSON形式返回其数据。 当我说我在请求中传递2个ID 1018089108070373346和2017089208070373346时,响应如下所示: p>

  {
“ data”:{
“ 1018089108070373346”:{\  n“名称”:“一家不错的酒店”,
“成功”:是
},
“ 2017089208070373346”:{
“名称”:“另一家不错的酒店”,
“成功”:是
  } 
} 
} 
  code>  pre> 
 
 

由于我是Golang的新手,因此我使用了 http://mholt.github.io/json-to-go/ 以获得上述响应的结构表示。 我得到的是: p>

  type自动生成的结构{
数据结构{
 Num1017089108070373346结构{
 Name string`json:“ name”`
 Success bool`json  :“ success”`
}`json:“ 1017089108070373346”`
 Num2017089208070373346 struct {
 Name string`json:“ name”`
 Success bool`json:“ success”`
}`json:“ 2017089208070373346  “`
}`json:” data“`
} 
  code>  pre> 
 
 

我无法使用上述结构,因为实际的id值和我通过的id数 每次可以不同,返回的JSON将具有不同的密钥。 如何将这种情况映射到结构? p>

谢谢 p> div>

Use a map:

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

Run it on the playground

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

test.json

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

test.go

package main

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

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

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

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

    jsonParser := json.NewDecoder(jsonFile)
    var filedata Response
    if err = jsonParser.Decode(&filedata); err != nil {
        fmt.Println("Error while reading test file.
", 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