๐ŸŽ“ A1Learner
๐Ÿ”
0 of 34 lessons completed

Go JSON

JSON is a text format for data with named fields. The encoding/json package turns Go values into JSON text and back.

Marshal a struct with tags

A struct tag sits in backticks after a field. The tag sets the name that the field gets in the JSON text.

package main

import (
	"encoding/json"
	"fmt"
)

type Book struct {
	Title  string `json:"title"`
	Author string `json:"author"`
	Pages  int    `json:"pages"`
}

func main() {
	book := Book{Title: "Go Basics", Author: "Hana Reyes", Pages: 120}
	data, err := json.Marshal(book)
	if err != nil {
		fmt.Println("Could not build JSON")
		return
	}
	fmt.Println(string(data))
}

Pretty JSON with MarshalIndent

MarshalIndent does the same job as Marshal with extra arguments. The last argument gives the spaces that start each inner line.

package main

import (
	"encoding/json"
	"fmt"
)

type Book struct {
	Title string `json:"title"`
	Pages int    `json:"pages"`
}

func main() {
	book := Book{Title: "Go Basics", Pages: 120}
	data, err := json.MarshalIndent(book, "", "  ")
	if err != nil {
		fmt.Println("Could not build JSON")
		return
	}
	fmt.Println(string(data))
}

Unmarshal into a struct

Unmarshal reads JSON text into a struct value. The tag names tell Unmarshal which field each name fills.

package main

import (
	"encoding/json"
	"fmt"
)

type Book struct {
	Title string `json:"title"`
	Pages int    `json:"pages"`
}

func main() {
	text := []byte(`{"title":"Go Basics","pages":120}`)
	var book Book
	err := json.Unmarshal(text, &book)
	if err != nil {
		fmt.Println("Could not read JSON")
		return
	}
	fmt.Println(book.Title)
	fmt.Println(book.Pages)
}

Unmarshal into a map

A map can hold JSON data when no struct shape is fixed. Println prints the whole map with its keys in sorted order.

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	text := []byte(`{"title":"Go Basics","pages":120}`)
	values := make(map[string]any)
	err := json.Unmarshal(text, &values)
	if err != nil {
		fmt.Println("Could not read JSON")
		return
	}
	fmt.Println(values)
}

A nested struct becomes nested JSON

A JSON object is a group of named fields inside braces. The inner struct value becomes an inner object in the JSON text.

package main

import (
	"encoding/json"
	"fmt"
)

type Author struct {
	Name string `json:"name"`
}

type Book struct {
	Title  string `json:"title"`
	Author Author `json:"author"`
}

func main() {
	book := Book{Title: "Go Basics", Author: Author{Name: "Hana Reyes"}}
	data, err := json.Marshal(book)
	if err != nil {
		fmt.Println("Could not build JSON")
		return
	}
	fmt.Println(string(data))
}

Example

package main

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

type Book struct {
	Title  string `json:"title"`
	Author string `json:"author"`
	Pages  int    `json:"pages"`
}

func main() {
	book := Book{Title: "Go Basics", Author: "Hana Reyes", Pages: 120}
	data, err := json.Marshal(book)
	if err != nil {
		fmt.Println("Could not build JSON")
		return
	}
	fmt.Println(string(data))
	err = os.WriteFile("book.json", data, 0644)
	if err != nil {
		fmt.Println("Could not write the file")
		return
	}
	saved, err := os.ReadFile("book.json")
	if err != nil {
		fmt.Println("Could not read the file")
		return
	}
	var back Book
	err = json.Unmarshal(saved, &back)
	if err != nil {
		fmt.Println("Could not read JSON")
		return
	}
	fmt.Println(back.Title)
	fmt.Println(back.Pages)
}

Key points

  • JSON is a text format that names each field of data.
  • Use json.Marshal to turn a value into JSON text.
  • Use json.Unmarshal to read JSON text into a value.
  • Struct tag: a label in backticks after a field that sets the field name in JSON.
  • Use json.MarshalIndent to spread JSON text over lines with spaces.
  • Unmarshal into a map gives one value for each JSON field name.
  • A struct value inside another struct becomes a JSON object inside the outer object.

In this example, Marshal turns the book into one line of JSON text. The print shows that line. WriteFile saves the same bytes to book.json. ReadFile reads the bytes back, and Unmarshal fills a new Book value. The last two prints show the title and the page count from the new value.

Note

A field that starts with a small letter stays out of the JSON text.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Go Playground

Exercise

What does the tag `json:"pages"` after a field do?