Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang :How to parse/unmarshal/decode a json array API response?

I am trying to parse the response from Wikipedia's API located at https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/Smithsonian_Institution/daily/20160101/20170101 into an array of structs of which I will proceed to print out the view count

However, the code that I have tried to implement in order to achieve this returns nothing in the terminal when I build and run it?

The code I am failing to succeed with is as follows.

   type Post struct {
    Project string `json:"project"`
    Article string `json:"article"`
    Granularity string `json:"granularity"`
    Timestamp string `json:"timestamp"`
    Access string `json:"access"`
    Agent string `json:"agent"`
    Views int `json:"views"`
}

func main(){
    //The name of the wikipedia post
    postName := "Smithsonian_Institution"

    //The frequency of
    period := "daily"

    //When to start the selection
    startDate := "20160101"

    //When to end the selection
    endDate := "20170101"

    url := fmt.Sprintf("https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/all-agents/%s/%s/%s/%s", postName, period, startDate, endDate)

    //Get from URL
    req, err := http.Get(url)
    if err != nil{
        return
    }
    defer req.Body.Close()

    var posts []Post

    body, err := ioutil.ReadAll(req.Body)
    if err != nil {
        panic(err.Error())
    }

    json.Unmarshal(body, &posts)

    // Loop over structs and display the respective views.
    for p := range posts {
        fmt.Printf("Views = %v", posts[p].Views)
        fmt.Println()
    }

}

What is the optimal method of receiving a json response from a API such as the one mentioned above and thereafter parsing that array into an array of structs, which can then be inserted into a datastore or printed out accordingly.

Thanks

like image 665
Natalie Williams Avatar asked Apr 26 '17 03:04

Natalie Williams


People also ask

How do I read an array of JSON objects in Golang?

Golang provides multiple APIs to work with JSON including to and from built-in and custom data types using the encoding/json package. To parse JSON, we use the Unmarshal() function in package encoding/json to unpack or decode the data from JSON to a struct.

How do you parse a response body in Go?

In Go, you can use the io. ReadAll() function (or ioutil. ReadAll() in Go 1.15 and earlier) to read the whole body into a slice of bytes and convert the byte slice to a string with the string() function. To exclude the response body from the output, change the boolean argument to httputil.

How does JSON Unmarshal work Golang?

To unmarshal a JSON array into a slice, Unmarshal resets the slice length to zero and then appends each element to the slice. As a special case, to unmarshal an empty JSON array into a slice, Unmarshal replaces the slice with a new empty slice.


1 Answers

Struct declarations can be nested inside one another.

The following struct should be convertable from that json:

type resp struct {
    Items []struct {
        Project string `json:"project"`
        Article string `json:"article"`
        Granularity string `json:"granularity"`
        Timestamp string `json:"timestamp"`
        Access string `json:"access"`
        Agent string `json:"agent"`
        Views int `json:"views"`
    } `json:"items"`
}

I generated that with json-to-go, which is a great time saver when working with JSON APIs.

like image 129
Ammar Bandukwala Avatar answered Sep 28 '22 12:09

Ammar Bandukwala