In this article, we will discuss different ways we can read JSON data format into a map, struct, decode and encode, and save data into a JSON format in Golang.
Modern applications such as REST-APIs, Microservices, and MobileApps use JSON for easy communication across the services mainly for storing and transferring data across the server and web application.
We shall discuss the following:-
- What is JSON?
- Read JSON Data to map
- Read JSON Data to struct
- Save JSON Data
- Using
Marshal()
(converting from a Go data type to an encoding) - Using
UnMarshal()
(converting to a Go data type)
What is JSON?
JSON is a JavaScript Object Notation very lightweight, text-based representation of javascript object literals, arrays, and scalar data type and language-independent data interchange format. It originated in the Javascript programming language and has built-in support from all other programming languages. Its main purpose is used to store and transfer data from server to web and vice versa.
Example of a JSON data format.
{
"companyname":"GoLinuxCloud",
"year":"5",
"services":"Online Academy"
"staffs":"10"
}
In JSON, the data are in Key/value pairs separated by a comma. The key must be a string based on the JSON schema definition while the value can be of a different scalar/type i.e string, object, list of objects, or strings.
Go offers built-in support for JSON encoding and decoding, including to and from built-in and custom data types.
Method-1: Reading JSON data To Map in Go
In Go, encoding/json package contains json.Unmarshal()
method which parses JSON-encoded data and stores the results as pointer values by the interface method. In case the interface is nil or zero pointers, we shall obtain an error from json.Unmarshal()
method as InvalidUnmarshalError
. The interface accepts data in either object or an array format. Go interface is suitable when the data is unstructured hence no struct is created and desired output can be achieved by parsing the JSON data.
Example
//main.go
package main
import (
"encoding/json"
"fmt"
)
// sample json object to be parsed
var companyJSON = `{
"name" : "GOLinuxCloud",
"years_of_service" : "5",
"nature_of_company" : "Online Academy",
"no_of_staff" : "10"
}`
func main() {
// Declared an empty map interface
var dataResult map[string]interface{}
// Unmarshal the JSON to the interface.its same as decode
err := json.Unmarshal([]byte(companyJSON), &dataResult)
if err != nil {
fmt.Println(err)
}
// Print elements in map on the terminal the key and its value
for key, value := range dataResult {
fmt.Printf("%s : %v \n", key, value)
}
}
Output:
$ go run main.go
name : GOLinuxCloud
years_of_service : 5
nature_of_company : Online Academy
no_of_staff : 10
Explanation
We he imported all required packages namely :- "encoding/json", "fmt"
. fmt package contain Printf()
function to display key and values while encoding/json has unmarshall()
function to convert data.
var companyJSON =`{}`
Defined and declared company JSON as a global variable of specific JSON.
main()
:- Declared an empty interface of map of string map[string]interface{}
to hold the parsed data from companyJSON variable. To convert the json object to a map, we used json.Unmarshall()
function which unmarshall the json string by converting it byte into the map[string] interface and stores the value pointed to the interface as well as checking if there is error encountered during conversion.
We can finally create a for key, value:= range dataResult{}
to loop through the mapped data and print the key and value because the data is stored in key/value pair in a map.
Method-2: Reading JSON data into struct in Go
Example-1: Decode JSON data into struct
Decoding json data into struct , the data must be of a certain format defined before. for example company details
`{
"companyname":"GoLinuxCloud",
"year":"5",
}`
Its a formatted data and we can create a struct for that data to be parsed.
Example
package main
import (
"encoding/json"
"fmt"
)
// sample json object to be parsed
var companyJSON = `{
"name" : "GOLinuxCloud",
"year" : "5"}`
type Company struct {
Name string
Year string
}
func main() {
//initialize the struct
var company Company
// Unmarshal the JSON string into byte into &company struct to store parsed data
err := json.Unmarshal([]byte(companyJSON), &company)
if err != nil {
fmt.Println(err)
}
// Print struct values
fmt.Printf("Name: %s, \nYear: %s \n", company.Name, company.Year)
}
Output:
$ go run main.go
Name: GOLinuxCloud,
Year: 5
Explanation
We define struct based on the JSON raw data provided. the struct attributes must be the same as one in the json though the json attributes are case insensitive
Example-2: Decoding JSON Array into struct
We can as well read json data in an array structure into Go struct.
package main
import (
"encoding/json"
"fmt"
)
// sample json object to be parsed
var companyJSON = `[{"name" : "GOLinuxCloud","year" : "2000"},
{"name" : "Google","year" : "1998"}]`
type Company struct {
Name string
Year string
}
func main() {
//initialize the struct
var company []Company
// Unmarshal the JSON string into byte into &company struct to store parsed data
err := json.Unmarshal([]byte(companyJSON), &company)
if err != nil {
fmt.Println(err)
}
// Print array of values in the struct
fmt.Printf("Company : %+v \n", company)
}
Output:
$ go run main.go Company : [{Name:GOLinuxCloud Year:2000} {Name:Google Year:1998}]
Method-3: Writing data into JSON file in Go
In Go, encodig/jsn package provide a marshalIndent
function which encode json data with an indentation \n,\t,comma or space,
. ioutil pacjkage enable us to save data into a file using writeFile function which accepts a file_name, well indented json data and file write and read permission 0644 means file is readable by all the user groups, but writable by the user only. i.e ioutil.WriteFile(filename,data,0644)
Example
// main
package main
import (
"encoding/json"
"io/ioutil"
"log"
)
//struct
type company struct {
Name string
Year int64
Description string
Country string
Address Address
}
type Address struct {
Street string
City string
Region string
PostCode int64
}
var saveJSON = "struct_to_Json.json"
func main() {
// sample data from struct
companyData := []company{
{Name: "Google", Year: 1998, Description: "Cloud services", Country: "USA", Address: Address{
Street: "Parkway",
City: "California",
Region: "US",
PostCode: 1600,
}},
{Name: "GoLinuxCloud", Year: 2019, Description: "Provides Online study material", Country: "USA", Address: Address{
Street: "Broadway",
City: "NewYork",
Region: "US",
PostCode: 1000,
}},
}
jsonData, err := json.MarshalIndent(companyData, "", " ")
if err != nil {
log.Fatalf("could not convert struct data into json file: %v", err)
}
//Save Json Data into a json file
if err = ioutil.WriteFile(saveJSON, jsonData, 0644); err != nil {
log.Fatalf("could not saveJSON file: %v", err)
}
}
Output:
$ go run main.go $ cat struct_to_Json.json
[
{
"Name": "Google",
"Year": 1998,
"Description": "Cloud services",
"Country": "USA",
"Address": {
"Street": "Parkway",
"City": "California",
"Region": "US",
"PostCode": 1600
}
},
{
"Name": "GoLinuxCloud",
"Year": 2019,
"Description": "Provides Online study material",
"Country": "USA",
"Address": {
"Street": "Broadway",
"City": "NewYork",
"Region": "US",
"PostCode": 1000
}
}
]
Explanation
We have imported all required packages. companyData := []company{}
Define a sample struct, initialized it and added array of data.
jsonData, err := json.MarshalIndent(companyData, "", " ")
we have used space character for indentation,. you can use \t tab or space for formatting data.
Finally, we pass formatted data into ioutil.writefile()
function to save the data into a file.
Method-4: Using Marshal() In Go
Go encoding/json package has Marshall function used for encoding JSON string from an original data type.
We make use of the following function func Marshal(v interface{}) ([]byte, error)
it accepts json data to be encoded and returns an array of bytes as an output and error. errors should be handled during the program.
Example
package main
import (
"encoding/json"
"fmt"
)
type Company struct {
Name string `json:"name"`
Year string `json:"year"`
}
func main() {
company := &Company{
Name: "GoLinuxCloud",
Year: "2019",
}
//Encoding company data using Marshall function
jsondata, err := json.Marshal(company)
if err != nil {
fmt.Println(err)
}
// jsonData variable contains a data in form og bytes.
// we have handled error in cas if encountered during execution
fmt.Printf("Bytes : %v \n", jsondata) // will show the data inform of bytes
// we need to convert the bytes of jsondata into json string by typecast it to a string function
jsonOutput := string(jsondata)
fmt.Printf("JSONDATA: %v\n", jsonOutput)
}
Output:
$ go run main.go
Bytes : [123 34 110 97 109 101 34 58 34 71 111 76 105 110 117 120 67 108 111 117 100 34 44 34 121 101 97 114 34 58 34 50 48 49 57 34 125]
JSONDATA: {"name":"GoLinuxCloud","year":"2019"}
Method-5: Using UnMarshal() in Go
Go ,encoding/json package provides json.Unmashall()
function which decodes json data format into a defined struct. Here is the function syntax used func Unmarshal(data []byte, v interface{}) error
results are stored as value pointer to an interface v, incase the interface is nil the function return InvalidUnMarshallError
which must be handled during the program.
Example
//main.go
package main
import (
"encoding/json"
"fmt"
)
type Data struct {
Msg string `json:"msg"`
}
// data in jsonformat to be decoded
var jsonSample = `{"Msg":"Hello from GoLinuxCloud"}`
func main() {
// struct instance
var data Data
//decoding Data struct from json formatted data
err := json.Unmarshal([]byte(jsonSample), &data)
if err != nil {
fmt.Println(err)
}
// print data after decoding
fmt.Printf(" %s\n", data)
}
Output:
$ go run main.go
{Hello from GoLinuxCloud}
Summary
In this article, we have used Golang encoding/json package which was helpful in reading JSON data into a map, struct, and save_json files using these JSON functions marshal ,unmarshal and MarshalIndent
.
References
Encoding/json documentation
Json and Go
Go by Example