Files
2025-11-17 23:25:36 +09:00

4.3 KiB
Raw Permalink Blame History

Working with JSON

Lets learn how to work with JSON data.

The Go standard library includes encoding/json, which is for working with JSON data. Additionally, Go allows us to add support for JSON fields in Go structures using tags. Tags control the encoding and decoding of JSON records to and from Go structures. But first, we should talk about marshaling and unmarshaling JSON records.

Using Marshal() and Unmarshal()

Both the marshaling and unmarshaling of JSON data are important procedures for working with JSON data using Go structures. Marshaling is the process of converting a Go structure into a JSON record. We usually want that for transferring JSON data via computer networks or for saving it on disk. Unmarshaling is the process of converting a JSON record given as a byte slice into a Go structure. We usually want that when receiving JSON data via computer networks or when loading JSON data from disk files.

Note: The number one bug when converting JSON records into Go structures and vice versa is not making the required fields of our Go structures exported. When we have issues with marshaling and unmarshaling, begin our debugging process from there.

Coding example

The code in encodeDecode.go illustrates both the marshaling and unmarshaling of JSON records using hardcoded data for simplicity:

package main

import (
	"encoding/json"
	"fmt"
)

type UseAll struct {
	Name    string `json:"username"`
	Surname string `json:"surname"`
	Year    int    `json:"created"`
}

What the previous metadata tells us is that the Name field of the UseAll structure is translated to username in the JSON record, and vice versa; the Surname field is translated to surname, and vice versa; and the Year structure field is translated to created in the JSON record, and vice versa. This information has to do with the marshaling and unmarshaling of JSON data. Other than this, we treat and use UseAll as a regular Go structure.

func main() {
  useall := UseAll{Name: "Mike", Surname: "Tsoukalos", Year: 2021}

	// Regular Structure
	// Encoding JSON data -> Convert Go Structure to JSON record with fields
	t, err := json.Marshal(&useall)
}

The json.Marshal() function requires a pointer to a structure variable—its real data type is an empty interface variable—and returns a byte slice with the encoded information and an error variable.

if err != nil {
  fmt.Println(err)
} else {
  fmt.Printf("Value %s\n", t)
}

// Decoding JSON data given as a string
str := `{"username": "M.", "surname": "Ts", "created":2020}`

JSON data usually comes as a string.

	// Convert string into a byte slice
	jsonRecord := []byte(str)

However, as json.Unmarshal() requires a byte slice, we need to convert that string into a byte slice before passing it to json.Unmarshal().

	// Create a structure variable to store the result
	temp := UseAll{}
	err = json.Unmarshal(jsonRecord, &temp)

The json.Unmarshal() function requires the byte slice with the JSON record and a pointer to the Go structure variable that is going to store the JSON record and returns an error variable.

	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Data type: %T with value %v\n", temp, temp)
	}

Running encodeDecode.go produces the next output:

# go run encodeDecode.go
Value {"username":"Mike","surname":"Tsoukalos","created":2021}
Data type: main.UseAll with value {M. Ts 2020}
package main

import (
	"encoding/json"
	"fmt"
)

type UseAll struct {
	Name    string `json:"username"`
	Surname string `json:"surname"`
	Year    int    `json:"created"`
}

func main() {
	useall := UseAll{Name: "Mike", Surname: "Tsoukalos", Year: 2021}

	// Regular Structure
	// Encoding JSON data -> Convert Go Structure to JSON record with fields
	t, err := json.Marshal(&useall)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Value %s\n", t)
	}

	// Decoding JSON data given as a string
	str := `{"username": "M.", "surname": "Ts", "created":2020}`
	// Convert string into a byte slice
	jsonRecord := []byte(str)
	// Create a structure variable to store the result
	temp := UseAll{}
	err = json.Unmarshal(jsonRecord, &temp)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Data type: %T with value %v\n", temp, temp)
	}
}