使用Golang映射对结构的响应

时间:2018-01-03 16:40:17

标签: go

我正在尝试使用Golang将API的响应映射到结构。

我在浏览器中查看链接时返回的JSON如下:

{
"GBP": 657.54
}

我只是想将它映射到一个简单的结构,如下所示:

type Price struct {
    Name  string
    Value float64
}

这是我目前的代码。

func FetchCoinPrice(fsym string, tsyms string) Price {
    url := fmt.Sprintf("https://min-api.cryptocompare.com/data/price?fsym=" + fsym + "&tsyms=" + tsyms)

    fmt.Println("Requesting data from " + url)

    price := Price{}

    // getting the data using http
    request, err := http.Get(url)
    if err != nil {
        log.Fatal(err.Error())
    }

    // Read the response body using ioutil
    body, err := ioutil.ReadAll(request.Body)
    if err != nil {
        log.Fatal(err.Error())
    }

    defer request.Body.Close()

    if request.StatusCode == http.StatusOK {
        json.Unmarshal(body, &price)
    }

    return price

}

目前我收到的是一个空结构,我知道该链接正在恢复正确的数据,我已经在浏览器中对其进行了测试。

2 个答案:

答案 0 :(得分:5)

映射不起作用。相反,您应该使用地图:

    data := []byte(`{
       "GBP": 657.54
     }`)

    priceMap := map[string]float64{}
    err := json.Unmarshal(data, &priceMap)
    // Check your errors!
    if err != nil {
      log.Fatal(err.Error())
    }
    fmt.Println(priceMap)

这将打印:

map[GBP:657.54]

然后,您可以迭代地图并构建上面提到的结构,或者只是在知道货币时直接访问该条目。例如:priceMap["GBP"]

您应该检查错误,特别是如果您没有从Unmarshal获得预期的输出。

答案 1 :(得分:2)

问题在于,解组者无法猜测JSON对象中的 keys 应该对应于结构中的某些。 Golang JSON映射根本不起作用。

但是,您可以将“价格”类型implement json.Unmarshaler反序列化为浮点数(map[string]float64),然后确保形状正确并相应地填充结构:

func (p *Price) UnmarshalJSON(bs []byte) error {
  kvs := map[string]float64{}
  err := json.Unmarshal(bs, &kvs)
  if err != nil {
    return err
  }
  if len(kvs) != 1 {
    return fmt.Errorf("expected 1 key, got %d", len(kvs))
  }
  for name, value := range kvs {
    p.Name, p.Value = name, value
  }
  return nil
}

func main() {
  jsonstr := `[{"GBP":657.54},{"USD":123.45}]`
  ps := []Price{}
  err := json.Unmarshal([]byte(jsonstr), &ps)
  if err != nil {
    panic(err)
  }
  // ps=[]main.Price{
  //   main.Price{Name:"GBP", Value:657.54},
  //   main.Price{Name:"USD", Value:123.45}
  // }
}