LanguagesWorking with JSON files in Go

Working with JSON files in Go

Go Programming ``

JSON (JavaScript Object Notation) is a popular data format derived from the object literals of JavaScript as defined in the ECMAScript programming language standard. It is a simple textual format that follows UTF-8 encoding and is particularly used for storage and transportation of data. The self describing nature of data representation enhances its readability and is widely accepted as an intermediary for data exchange across web programming or client/server communication.

Go provides standard library packages for encoding and decoding JSON objects but before going into that let us discuss JSON data representation a little more thoroughly. The article will show how we can use Go’s standard library to handle JSON files.

Read: Getting Started with Go Programming.

Data Representation in JSON

JSON can represent four primitive types: strings, numbers, Booleans and null. It can also represent structured types such as objects and arrays. A string in JSON is a sequence of zero or more Unicode characters and an object is nothing but an unordered collection of zero or more named/value pairs and. The name (of name/value pair) is a string and value can be any primitive or structured types such as string, number, Boolean, null, object or an array. An array represents an ordered sequence of zero or more values.

  • Data is represented as named/value pairs
  • Uses comma as a separator
  • Objects are encompassed within curly braces
  • An array of data is hold within square brackets

Example of a JSON object

A typical JSON object may look like this:

{
	“id”: 101,
	“title”: “Modern Calculus”,
	“publisher”: {
		“by”: “Dover Publications”,
		“edition”: 2012
	}	
}

Note that the JSON object contains keys like “id”, “title” and it is associated with the values pair such as -101 and “Modern Calculus” respectively. Also note that in the above example the JSON object contains another object called “publisher” which also has a corresponding key/value pair. In this way an object may contain multiple nested inner objects represented in the similar fashion.

It is also simple to represent an array of objects. For example, an array of “book” objects can be represented as follows:

{
	“books”: [
		{“id”: 101, “title”: “Modern Calculus”, “publisher”:{“by”:”Dover Publication”, “edition”:1994}},
		{“id”: 102, “title”: “Graph Theory”, “publisher”:{“by”:”Dover Publication”, “edition”:2004}},
		{“id”: 103, “title”: “Automata Theory”, “publisher”:{“by”:”Pearson”, “edition”:2008}}
	]
}

Here, the array contains three objects. Notice how square brackets are used to represent an array, an ordered collection of objects.

Read: Understanding Structs in Go.

How to Encode and Decode JSON Data

Observe that the data representation in JSON can easily be ported to struct type in Go. Also note that, as we encode and decode a struct type to and from JSON, the struct field names become the key of the key/value pair of JSON data type. However, this is a default behavior; we can always provide an explicit JSON tag to represent the key as follows:

 

type User struct {
	Id       	int        	`json:"ID"`
	Name     	string     	`json:"UserName"`
	Password 	string     	`json:"UserPassword"`
	LoggedAt 	time.Time  	`json:"LoginTime"`
}

In most cases the default behavior is good enough.

Encoding Data in JSON and Go

The json.Marshal function of the encoding/json package provides the necessary functionalities for encoding a struct type to JSON data. After encoding the function returns a byte representation of the encoded JSON value. It is quite simple to encode a struct type to its corresponding JSON data. We can do it as follows:

type User struct {
	Id       int
	Name     string
	Password string
	LoggedAt time.Time
}

//creating empty structure
user0 := User{}
//populating the structure
user0.Id = 1122
user0.Name = "Peter"
user0.Password = "Parker"
user0.LoggedAt = time.Now()
//encoding 
user0Byte, _ := json.Marshal(user0)
fmt.Println(string(user0Byte))

Also, we can do it as follows. Notice how we have cast byte value returned by the Marshal function to its equivalent string for the purpose of printing meaningful value in standard output.

user1 := User{101, "Alice", "wonderland", time.Now()}
jsonByte, _ := json.Marshal(user1)
fmt.Println(string(jsonByte))

Decoding Data in JSON and Go

Decoding is just the reverse process where we use json.Unmarshal function. This function takes encoded JSON data and a reference to a variable where the encoded JSON is to be written. It returns an error if it occurs else nil is returned. The following Golang code snippet illustrates the idea:

bytes1 := []byte(`{"Id":102,"Name":"Bob","Password":"123xyz","LoggedAt":"2021-10-23T16:08:21.124481-04:00"}`)
var user2 User
json.Unmarshal(bytes1, &user2)
fmt.Println(user2)

var user4 User
json.Unmarshal(user0Byte, &user4)
fmt.Println(user4)

Encoding and Decoding Example in JSON and Golang

Let’s put it all together into a runnable program. Note that it’s a bare bone program to experiment with; to keep things simple we have ignored error values returned by the Marshal and Unmarshal functions.

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type User struct {
	Id       int
	Name     string
	Password string
	LoggedAt time.Time
}

func main() {
    //--------------------------------------
	//encoding / Marshalling
    //--------------------------------------
	user0 := User{}
	user0.Id = 1122
	user0.Name = "Peter"
	user0.Password = "Parker"
	user0.LoggedAt = time.Now()

	user0Byte, _ := json.Marshal(user0)
	fmt.Println(string(user0Byte))

	user1 := User{101, "Alice", "wonderland", time.Now()}
	jsonByte, _ := json.Marshal(user1)
	fmt.Println(string(jsonByte))

    //--------------------------------------
	//decoding / Unmarsalling
    //--------------------------------------
	bytes1 := []byte(`{"Id":102,"Name":"Bob","Password":"123xyz","LoggedAt":"2021-10-23T16:08:21.124481-04:00"}`)
	var user2 User
	json.Unmarshal(bytes1, &user2)
	fmt.Println(user2)

	var user4 User
	json.Unmarshal(user0Byte, &user4)
	fmt.Println(user4)
}

Reading and Writing JSON Files in Go

Often we need to create JSON files where we may store configuration information or any other information. It is actually pretty simple to read and write data to and from JSON files using the Go standard library.

package main

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


type User struct {
	Id       int
	Name     string
	Password string
	LoggedAt time.Time
}

func main() {
	
	user := User{}
	user.Id = 1122
	user.Name = "Peter"
	user.Password = "Parker"
	user.LoggedAt = time.Now()
	//...................................
	//Writing struct type to a JSON file
	//...................................
	content, err := json.Marshal(user)
	if err != nil {
		fmt.Println(err)
	}
	err = ioutil.WriteFile("userfile.json", content, 0644)
	if err != nil {
		log.Fatal(err)
	}
	//...................................
	//Reading into struct type from a JSON file
	//...................................
	content, err = ioutil.ReadFile("userfile.json")
	if err != nil {
		log.Fatal(err)
	}
	user2 := User{}
	err = json.Unmarshal(content, &user2)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Id:%d, Name:%s, Password:%s, LoggedAt:%v", user2.Id, user2.Name, user2.Password, user2.LoggedAt)
}

For writing struct types into a JSON file we have used the WriteFile function from the io/ioutil package. The data content is marshalled/encoded into JSON format. The WriteFile function writes data to a file by filename. If the file does not exist, it creates the file with the content provided and the permission provided as a parameter to it. Similarly, the ReadFile function reads the file and the content is unmarshalled/decoded into a struct type.

JSON and Go Programming Tutorial

JSON is a lightweight data interchange format that is not only easy for humans to read and write but also easy for machines to parse and generate. Perhaps, simplicity is the reason behind increasing popularity of JSON particularly for data transfer over the network. The Go standard library provides excellent support to write compact code in dealing with JSON. There is another format called XML which is also used for similar purposes. Go provides excellent support for XML too.

Read more Go and Golang programming tutorials.

Latest Posts

Related Stories