dwalsh
dwalsh

Reputation: 145

Working with JSON data in Go from API Call

I mainly program in python and am in the process of teaching myself some Go!

I've come to a stumbling block in trying to parse JSON data from an api call and I am turning to the great community here for some advice! Nothing I can find online has worked yet so any advice, even if its just related to the rest of the code, would be helpful!

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
) 

//Time blah
type Time struct {
    Updated    string `json:"updated"`
    UpdatedISO string `json:"updatedISO"`
    Updateduk  string `json:"updateduk"`
}

//Currency blah blah
type Currency struct {
    Code  string  `json:"code"`
    Rate  float64 `json:"rate"`
    Descr string  `json:"description"`
    Rf    float64 `json:"rate-float"`
}

//Bpi blah
type Bpi struct {
    Usd []Currency `json:"USD"`
    Eur []Currency `json:"EUR"`
}

//ListResponse is a blah
type ListResponse struct {
    Time       []Time `json:"time"`
    Disclaimer string `json:"disclaimer"`
    Bpi        []Bpi  `json:"bpi"`
}

    func btcPrice() {

    url := "https://api.coindesk.com/v1/bpi/currentprice/eur.json"
    req, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    } else {
        data, err := ioutil.ReadAll(req.Body)
        if err != nil {
            fmt.Println("Error at the data stage: ", err)
        }
        // fmt.Println(string(data))
        var result ListResponse
        json.Unmarshal(data, &result)
        fmt.Println(result)
    }
}
func main() {
    btcPrice()
}

Basically the code above is to make an api call, take the JSON data and manipulate it using my structs above. (I may be going at this the wrong way altogether so if that's the case call me for it).

Here is where things go belly up for me. The JSON returned is the following:

{
   "time":{
      "updated":"Dec 10, 2017 20:41:00 UTC",
      "updatedISO":"2017-12-10T20:41:00+00:00",
      "updateduk":"Dec 10, 2017 at 20:41 GMT"
   },
   "disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
   "bpi":{
      "USD":{
         "code":"USD",
         "rate":"15,453.3888",
         "description":"United States Dollar",
         "rate_float":15453.3888
      },
      "EUR":{
         "code":"EUR",
         "rate":"13,134.4532",
         "description":"Euro",
         "rate_float":13134.4532
      }
   }
}

What I want to be able to do is access the json data sets individually, but the issue appears to be in my structs. If I call a basic print (commented in go code above for you to see), the whole data set from the json prints.But when I use the result code and json.unmarshal it only gives me the disclaimer, i.e the part of the struct simply labelled as of type string.

I may seem to be rambling and will clarify statements if they are questioned in the comments.

To Summarise:

Upvotes: 0

Views: 562

Answers (1)

leninhasda
leninhasda

Reputation: 1740

You have problem in your structure. If you see the json returned by the api call there is no array value for time and bpi key, all of them are object. Same goes for USD and EUR key.

And there are two more typos/mistake as well:

  1. rate is string not float. (you have to convert to float after reading it as string)
  2. rate-float should be rate_float

Here is the full working one (worked for me):

//Currency blah blah
type Currency struct {
    Code  string  `json:"code"`
    Rate  string  `json:"rate"`
    Descr string  `json:"description"`
    Rf    float64 `json:"rate_float"`
}

//Bpi blah
type Bpi struct {
    Usd Currency `json:"USD"`
    Eur Currency `json:"EUR"`
}

//ListResponse is a blah
type ListResponse struct {
    Time       Time   `json:"time"`
    Disclaimer string `json:"disclaimer"`
    Bpi        Bpi    `json:"bpi"`
}

Crosscheck with yours. Hope it helps!

Upvotes: 5

Related Questions