Go Tutorial · Standard Library · Lesson 26 of 30

Go JSON

Encode and decode JSON with encoding/json and struct tags.

Marshal and Unmarshal

json.Marshal turns Go values into JSON; json.Unmarshal parses JSON into a struct. Struct tags control the field names, and only exported (capitalised) fields are encoded:

Example 1
package main

import (
	"encoding/json"
	"fmt"
)

type Product struct {
	ID       int      `json:"id"`
	Name     string   `json:"name"`
	Price    float64  `json:"price,omitempty"`
	Tags     []string `json:"tags,omitempty"`
	internal string   // unexported: never encoded
}

func main() {
	p := Product{ID: 1, Name: "Mug", Price: 9.5, Tags: []string{"kitchen"}}
	data, _ := json.Marshal(p)
	fmt.Println(string(data))

	pretty, _ := json.MarshalIndent(Product{ID: 2, Name: "Pen"}, "", "  ")
	fmt.Println(string(pretty))

	var decoded Product
	err := json.Unmarshal([]byte(`{"id": 3, "name": "Lamp", "price": 45, "unknown": true}`), &decoded)
	fmt.Printf("%+v %v\n", decoded, err)

	var anything map[string]any
	json.Unmarshal([]byte(`{"count": 3, "ok": true}`), &anything)
	fmt.Println(anything["count"], anything["ok"])
}

Output

{"id":1,"name":"Mug","price":9.5,"tags":["kitchen"]}
{
  "id": 2,
  "name": "Pen"
}
{ID:3 Name:Lamp Price:45 Tags:[] internal:} <nil>
3 true

Run this on your computer — see “Get Started” for setup.

Unknown shapes

Decode into map[string]any when you don't know the structure in advance (numbers become float64).

For HTTP, stream with json.NewDecoder(r.Body).Decode(&v) and json.NewEncoder(w).Encode(v).

Test yourself

Which struct fields does encoding/json include?

  1. All fields
  2. Only exported (capitalised) fields
  3. Only fields with tags
  4. Only string fields
Show answer

Answer: Only exported (capitalised) fields