Go JSON Encoding and Decoding
JSON (JavaScript Object Notation) is the standard format for exchanging data between systems — web APIs, config files, and services all use it. Go's encoding/json package converts Go structs to JSON text (encoding) and converts JSON text back into Go structs (decoding).
JSON and Go Types Mapping
| Go Type | JSON Type |
|---|---|
string | "text" |
int, float64 | 42, 3.14 |
bool | true / false |
[]T (slice) | [...] (array) |
map[string]T | {...} (object) |
| struct | {...} (object) |
nil | null |
Encoding – Struct to JSON
Use json.Marshal to convert a Go value into JSON bytes.
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
func main() {
p := Person{
Name: "Alice",
Age: 30,
Email: "alice@example.com",
}
data, err := json.Marshal(p)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(data))
}
Output:
{"name":"Alice","age":30,"email":"alice@example.com"}
Struct Tags Explained
type Person struct {
Name string `json:"name"`
}
│ │
│ └── key used in the JSON output
└──────────── backtick syntax for struct tags
Without a tag: field "Name" becomes "Name" in JSON
With tag: field "Name" becomes "name" in JSON
Pretty-Printed JSON
Use json.MarshalIndent to produce readable, formatted JSON.
package main
import (
"encoding/json"
"fmt"
)
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
func main() {
p := Product{ID: 1, Name: "Go Book", Price: 29.99}
data, _ := json.MarshalIndent(p, "", " ")
fmt.Println(string(data))
}
Output:
{
"id": 1,
"name": "Go Book",
"price": 29.99
}
Decoding – JSON to Struct
Use json.Unmarshal to convert JSON bytes into a Go struct.
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
func main() {
jsonData := `{"name":"Bob","age":25,"email":"bob@example.com"}`
var p Person
err := json.Unmarshal([]byte(jsonData), &p)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(p.Name) // Bob
fmt.Println(p.Age) // 25
fmt.Println(p.Email) // bob@example.com
}
Encoding and Decoding Flow
ENCODING (Marshal):
Go Struct ──► json.Marshal() ──► JSON bytes ──► string(data)
DECODING (Unmarshal):
JSON string ──► []byte(s) ──► json.Unmarshal() ──► Go Struct
Handling Optional Fields – omitempty
The omitempty option skips a field in the JSON output if the field has its zero value.
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age,omitempty"` // omit if 0
Nickname string `json:"nickname,omitempty"` // omit if ""
}
func main() {
u := User{Name: "Carol"}
data, _ := json.Marshal(u)
fmt.Println(string(data)) // {"name":"Carol"}
}
Decoding JSON Array
package main
import (
"encoding/json"
"fmt"
)
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
jsonData := `[{"id":1,"name":"Go"},{"id":2,"name":"Python"}]`
var items []Item
json.Unmarshal([]byte(jsonData), &items)
for _, item := range items {
fmt.Printf("ID: %d, Name: %s\n", item.ID, item.Name)
}
}
Output:
ID: 1, Name: Go
ID: 2, Name: Python
Key Points
- Use
json.Marshalto convert a Go value to JSON bytes - Use
json.Unmarshalto parse JSON bytes into a Go struct - Struct tags like
json:"name"control the key names in the JSON output omitemptyskips a field from JSON output when it holds a zero value- Use
json.MarshalIndentfor human-readable formatted JSON - Always pass a pointer to
json.Unmarshalso it can populate the struct
