Parsing JSON in GO is an Adventure

One of the tough things to do in Golang is parsing JSON! Yes, indeed its a challenge for novice like me. When it comes to Python and Ruby its an easy task thanks to JSON libraries which are pretty easy to use especially in Python.

I tried to create the struct for a complex and nested JSON data below by hands but was not succeeded after several attempts.

{
    "clients": [
        {
            "clientId": "dde46983-00000004-5cdac62e-5cdc1fc1-00025000-a4aa9156",
            "hostname": "A999US032WIN001",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/159.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "159.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 24
            }
        },
        {
            "clientId": "70f32834-00000004-5cdac630-5cdd6bf5-00195000-a4aa9156",
            "hostname": "a999us034cen001",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/170.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "170.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 6
            }
        },
        {
            "clientId": "e34f2de3-00000004-5cdac62d-5cdac62c-00015000-a4aa9156",
            "hostname": "a999us034nve001.usp01.xstream360.cloud",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/158.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "158.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 2
            }
        },
        {
            "clientId": "3084d369-00000004-5cdac62f-5cdd4e05-000e5000-a4aa9156",
            "hostname": "a999us034rhl001",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/167.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "167.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 6
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/172.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "172.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/173.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "173.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/174.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "174.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/176.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "176.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/175.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "175.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/177.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "177.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/180.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "180.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/178.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "178.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/187.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "187.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        },
        {
            "clientId": "82fa0d80-00000004-5cdac631-5ceb7989-01165000-a4aa9156",
            "hostname": "icehousetest",
            "links": [
                {
                    "href": "https://10.10.10.6:9090/nwrestapi/v2/global/clients/184.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                    "rel": "item"
                }
            ],
            "resourceId": {
                "id": "184.0.129.30.0.0.0.0.20.198.218.92.10.10.10.6",
                "sequence": 1
            }
        }
    ],
    "count": 14
}

After deep (re)searching using DuckDuckGo, I finally found an easier way to convert JSON to Structs with the help of JSON-to-Go tool. Many thanks to Matt Holt for making things simple for me.

Here is the screenshot of converting JSON to Strcuts. This is the major step which was made very easy using this tool. By now you we know that we should have access to JSON data which should be static and available locally for conversion.

Now the required strcuts and types are autocreated, its time to unmarshal JSON data to strcuts and access its values. Below is the full implementation of the code.

/*
Parse and convert JSON to structs using JSON-to-Go Tool
*/
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

// structs generated using https://mholt.github.io/json-to-go/
type AutoGenerated struct {
	Clients []struct {
		ClientID string `json:"clientId"`
		Hostname string `json:"hostname"`
		Links    []struct {
			Href string `json:"href"`
			Rel  string `json:"rel"`
		} `json:"links"`
		ResourceID struct {
			ID       string `json:"id"`
			Sequence int    `json:"sequence"`
		} `json:"resourceId"`
	} `json:"clients"`
	Count int `json:"count"`
}

func main() {
	var info AutoGenerated
	// Reading data from JSON File
	file, e := ioutil.ReadFile("clients.json")
	if e != nil {
		fmt.Printf("File error: %v\n", e)
		os.Exit(1)
	}
	//Unmarshal json data into struct info
	if err := json.Unmarshal(file, &info); err != nil {
		log.Fatal(err)
	}

	//fmt.Printf("%+v\n", info)
	fmt.Println("CLIENT-ID,HOSTNAME,RESOURCE-ID")

	//Iterate through each value and print required types
	for _, value := range info.Clients {
		fmt.Printf("%s,%s,%s\n", value.ClientID, value.Hostname, value.ResourceID.ID)
	}

}

Hope the above example code would help you to understand the steps to convert JSON to Structs, iterate through each key value and access those required types. Please leave your feedback if you found this useful and suggestions in the below Comments section.

Advertisements

Install and Configure Go/Golang on Raspberry Pi

Go/Golang is one of the hot programming languages while I’m typing this today.

Go is a programming language created at Google in 2009 by Robert Griesemer, Rob Pike and Ken Thompson. Go is a statically typed compiled, procedural language similar to C, with memory safety, garbage collection, structural typing, concurrency and other great features are bundled to make it better compared to other languages in the marketplace.

Docker, Kubernetes, Graphana, Hugo are some of the best apps written in Go. It has a robust set of libraries and app performance is better compared to other languages.

Today I’m starting my journey to learn Go/Golang and Google will be my mentor to install and setup Golang on my Raspbian OS/Raspberry Pi 3. To get the latest version use below steps instead of native package management tool such as apt.

Installation Steps:

  • Download the current stable version of Go available on the google’s official website. At the time of writing this tutorial, 1.12.4 is the stable version. Check the latest version here
cd ~ && curl -O https://dl.google.com/go/go1.12.4.linux-armv6l.tar.gz

Above command would change directory to your ‘Home’ directory and download Go compressed tar file using ‘Curl’

  • Extract compressed tar file and place it inside /usr/local directory. Please note root level access or sudo access required to perform this step.
sudo tar -C /usr/local -xzvf go1.12.4.linux-armv6l.tar.gz
  • Set Path variables to avoid typing complete path and in order to access binaries or libraries of Go by the Raspbian OS. Open ~/.profile, a hidden file located in your ‘Home’ directory. Use nano or vi or subl to edit the file (subl ~/.profile). Add below lines at the end of the file.
export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
  • To take effect of the above changes made to the file ‘profile’, run the below command. The source command can be used to load any functions file into the current shell, script or a command prompt.
source ~/.profile
  • Create directory called ‘go’ in the ‘Home’ directory. All my codes are placed in the folder. Change the directory name as per choice but do change the GOPATH accordingly as mentioned above.
 mkdir $HOME/go 
  • Validate Go is working as expected or not by running below command
vb@pi:~ $  go version
go version go1.12.4 linux/arm
vb@pi:~ $

My first code in Go

Create a directory first_code in ‘go’ and write following content in the file and save it as first_code.go

mkdir -p $HOME/go/src/first_code 
{-p is used to create directory and its sub-directories at once}
package main

import "fmt"

func main() {
    fmt.Printf("My first code in Go Language!!!\n")
}

Now build and run the code. Change directory
to the first_code cd ~/go/src/first_code and run below commands

vb@pi:~/go/src/first_code $ go build
vb@pi:~/go/src/first_code $

vb@pi:~/go/src/first_code $ ./first_code
My first code in Go Language!!!
vb@pi:~/go/src/first_code $

Note:

Above steps are applicable to any Linux distributions just by changing the first step of downloading the compressed tar file. Change the architecture from arm6l to amd64 or as applicable to your hardware.

I am able to successfully setup GO on my Pi. Hope you’d also do the same and happy learning Go. If you have any issues or questions please mention them in the below comment section.