How to parserar JSON from Response in Golang

Asked

Viewed 89 times

-1

Once again, I on this site.

This time, I’m having a hard time parsing the API response I’m communicating with. The API in question is this one: https://api.brasil.io/v1/dataset/covid19/caso/data/? is_last=True&state=&city=&is_last=True

type Data struct {
    Count    int  `json:"1"`
    Next     bool `json:"null"`
    Previous bool `json:"null"`
    Results  []Cidades
}

type Cidades struct {
    Name      string `json:"city"`
    Confirmed int    `json:"confirmed"`
    Deaths    int    `json:"deaths"`
}

func main() {

   ... código acima disso que faz a requisição com Headers ...

    resp, err := client.Do(request)
    if err != nil {
        panic(err.Error())
    }

    body, readErr := ioutil.ReadAll(resp.Body)
    if readErr != nil {
        log.Fatal(readErr)
    }
    cidade := Cidades{}

    jsonErr := json.Unmarshal(body, &cidade)

    if jsonErr != nil {
        log.Fatal(jsonErr)
    }

    fmt.Println(cidade.Name)

}

All authentication is done correctly (thanks to this beautiful site).

I’ve tried to parser only "Results", but I can’t.

How can I do, for example, to assign Deaths to one variable and Confirmed to another, for example? From what I read, the http.Requests comes in byte, and when I try to parse for JSON, it returns only Results as string.

1 answer

0


To parse json you first need to "assemble" the data structures that represent a valid response from our API. Here is an example of json:

 var body = `{
        "count": 5616,
        "next": "https://api.brasil.io/v1/dataset/covid19/caso/data",
        "previous": null,
        "results": [
            {
                "city": "blabla",
                "city_ibge_code": "12",
                "confirmed": 54969,
                "confirmed_per_100k_inhabitants": 6145.4269,
                "date": "2021-02-22",
                "death_rate": 0.0176,
                "deaths": 968,
                "estimated_population": 894470,
                "estimated_population_2019": 881935,
                "is_last": true,
                "order_for_place": 343,
                "place_type": "state",
                "state": "AC"
            }]
    }`

After analyzing the received response, we should make a proper mapping of our response to our data structures.

A more suitable model would be:

type Cidade struct {
    Name         string      `json:"city"`
    Confirmed    int         `json:"confirmed"`
    Deaths       int         `json:"deaths"`
}
type ApiResultados struct {
    Count    int         `json:"count"`
    Next     string      `json:"next"`
    Previous string      `json:"previous"`
    Results  [] Cidade   `json:"results"`
}

Now that we have a representation of our response we have all the requirements necessary to turn the API response into data that we can handle in our application.

For this we use the function json. Unmarshall, that will transform our byte array into our object ApiResultados.

In this example I am assuming that already made the request we are just reading the bytes of our object resp, that has a response to a call we made in an api, follows the example:

defer resp.Body.Close()
body, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
    log.Fatal(readErr)
}
api_resultados := ApiResultados{}

jsonErr := json.Unmarshal(body, &api_resultados)

if jsonErr != nil {
    log.Fatal(jsonErr)
}

fmt.Println(api_resultados.Results[0].Name)
fmt.Println(api_resultados.Results[0].Deaths)

Note that after reading the bytes of the object resp we should call the Close() method of our object that has the answer in order to avoid memory leakage (memory Leaks), This behavior is documented here.

Answering the question

How can I, for example, assign Deaths to a variable and Confirmed in another, for example?

To make the assignment of variables just do:

confirmados := api_resultados.Results[0].Confirmed
mortes := api_resultados.Results[0].Deaths
fmt.Println(mortes)
fmt.Println(confirmados)

In this simplified example we have only one city within the array "results" if you have multiple elements just iterate with the repeat command for.

Here is a blog post that better details various ways to do the Information library in Golang

  • Thank you, it helped me understand the concept properly, again.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.