DEV Community

Cover image for Parse JSON API response in Go
billylkc
billylkc

Posted on • Edited on

54 7

Parse JSON API response in Go

(You can find my original post here - data-gulu.com)


Introduction

When you are hosting your model result as a micro-services, or scrapping data from websites, you will often find yourself working on some Restful API JSON object. In this post, I will show you how easily we can work with JSON data in Go.

Overview

  1. Get JSON response from sample API hosting site - reqres
  2. Generate go struct from the response - json-to-go
  3. Unmarshal JSON response to go struct
  4. Loop through the struct and print data from the result

Get Requests



package main

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

func main() {
    resp, err := http.Get("https://reqres.in/api/users?page=2")
    if err != nil {
        fmt.Println("No response from request")
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body) // response body is []byte
    fmt.Println(string(body))              // convert to string before print
}


Enter fullscreen mode Exit fullscreen mode

Result JSON



{"page":2,"per_page":6,"total":12,"total_pages":2,"data":[{"id":7,"email":"michael.lawson@reqres.in","first_name":"Michael","last_name":"Lawson","avatar":"https://reqres.in/img/faces/7-image.jpg"},{"id":8,"email":"lindsay.ferguson@reqres.in","first_name":"Lindsay","last_name":"Ferguson","avatar":"https://reqres.in/img/faces/8-image.jpg"},{"id":9,"email":"tobias.funke@reqres.in","first_name":"Tobias","last_name":"Funke","avatar":"https://reqres.in/img/faces/9-image.jpg"},{"id":10,"email":"byron.fields@reqres.in","first_name":"Byron","last_name":"Fields","avatar":"https://reqres.in/img/faces/10-image.jpg"},{"id":11,"email":"george.edwards@reqres.in","first_name":"George","last_name":"Edwards","avatar":"https://reqres.in/img/faces/11-image.jpg"},{"id":12,"email":"rachel.howell@reqres.in","first_name":"Rachel","last_name":"Howell","avatar":"https://reqres.in/img/faces/12-image.jpg"}],"support":{"url":"https://reqres.in/#support-heading","text":"To keep ReqRes free, contributions towards server costs are appreciated!"}}


Enter fullscreen mode Exit fullscreen mode

Convert JSON response

You can go to this site - JSON to go to convert JSON response to Go struct very easily.

Parse JSON to go struct

Unmarshal JSON to Go struct

You can then unmarshal the []byte from the GET response to the Response struct that we just auto-generated



// Generated go struct
type Response struct {
    Page       int `json:"page"`
    PerPage    int `json:"per_page"`
    Total      int `json:"total"`
    TotalPages int `json:"total_pages"`
    Data       []struct {
        ID        int    `json:"id"`
        Email     string `json:"email"`
        FirstName string `json:"first_name"`
        LastName  string `json:"last_name"`
        Avatar    string `json:"avatar"`
    } `json:"data"`
    Support struct {
        URL  string `json:"url"`
        Text string `json:"text"`
    } `json:"support"`
}

// snippet only
var result Response
if err := json.Unmarshal(body, &result); err != nil {   // Parse []byte to go struct pointer
    fmt.Println("Can not unmarshal JSON")
}
fmt.Println(PrettyPrint(result))


Enter fullscreen mode Exit fullscreen mode

Response struct preview (partial)



{
    "page": 2,
    "per_page": 6,
    "total": 12,
    "total_pages": 2,
    "data": [
    {
        "id": 7,
        "email": "michael.lawson@reqres.in",
        "first_name": "Michael",
        "last_name": "Lawson",
        "avatar": "https://reqres.in/img/faces/7-image.jpg"
    },
        {
        "id": 8,
        "email": "lindsay.ferguson@reqres.in",
        "first_name": "Lindsay",
        "last_name": "Ferguson",
        "avatar": "https://reqres.in/img/faces/8-image.jpg"
    }
    ]
}


Enter fullscreen mode Exit fullscreen mode

Finally loop through the data node and print out the FirstName of the result



// Loop through the data node for the FirstName
for _, rec := range result.Data {
fmt.Println(rec.FirstName)
}

Enter fullscreen mode Exit fullscreen mode




Complete code




package main

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

type Response struct {
Page int json:"page"
PerPage int json:"per_page"
Total int json:"total"
TotalPages int json:"total_pages"
Data []struct {
ID int json:"id"
Email string json:"email"
FirstName string json:"first_name"
LastName string json:"last_name"
Avatar string json:"avatar"
} json:"data"
Support struct {
URL string json:"url"
Text string json:"text"
} json:"support"
}

func main() {

<span class="c">// Get request</span>
<span class="n">resp</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="s">"https://reqres.in/api/users?page=2"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"No response from request"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">defer</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>
<span class="n">body</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">ioutil</span><span class="o">.</span><span class="n">ReadAll</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="p">)</span> <span class="c">// response body is []byte</span>

<span class="k">var</span> <span class="n">result</span> <span class="n">Response</span>
<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">json</span><span class="o">.</span><span class="n">Unmarshal</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">result</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>  <span class="c">// Parse []byte to the go struct pointer</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"Can not unmarshal JSON"</span><span class="p">)</span>
<span class="p">}</span>

<span class="c">// fmt.Println(PrettyPrint(result))</span>

<span class="c">// Loop through the data node for the FirstName</span>
<span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">rec</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">result</span><span class="o">.</span><span class="n">Data</span> <span class="p">{</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">rec</span><span class="o">.</span><span class="n">FirstName</span><span class="p">)</span>
<span class="p">}</span>
Enter fullscreen mode Exit fullscreen mode

}

// PrettyPrint to print struct in a readable way
func PrettyPrint(i interface{}) string {
s, _ := json.MarshalIndent(i, "", "\t")
return string(s)
}

Enter fullscreen mode Exit fullscreen mode




Demo

Parson JSON with Go

(You can find my original post here - data-gulu.com)

API Trace View

Struggling with slow API calls? 👀

Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (3)

Collapse
 
zeki profile image
Zeki Ahmet Bayar

Thanks for the post!

Collapse
 
maseo9 profile image
MasEo9

This was incredibly helpful, thanks so much for the post.

Collapse
 
anaroman profile image
Ana Roman

Thank you for the post, it was really helpful!

Billboard image

Try REST API Generation for Snowflake

DevOps for Private APIs. Automate the building, securing, and documenting of internal/private REST APIs with built-in enterprise security on bare-metal, VMs, or containers.

  • Auto-generated live APIs mapped from Snowflake database schema
  • Interactive Swagger API documentation
  • Scripting engine to customize your API
  • Built-in role-based access control

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay