Learn Go← Dashboard

fmt, io, os, bufio, encoding/json, net/http, time, slog, regexp, flag, embed.

encoding/json

JSON encoding lives in encoding/json. The two main functions are json.Marshal (Go → JSON) and json.Unmarshal (JSON → Go).

Marshaling — Go to JSON

go playground
Loading...

Only exported fields are marshaled. That's why Title and Year start with capital letters even when the JSON has lowercase keys — the tag handles the naming.

Unmarshaling — JSON to Go

go playground
Loading...

Pass a pointer to Unmarshal so it can fill in the fields.

Working with unknown JSON

When you don't know the shape, decode into map[string]any (or just any):

var v any
json.Unmarshal(data, &v)

m := v.(map[string]any)
fmt.Println(m["title"])

For very large or streaming JSON, use json.NewEncoder / json.NewDecoder — they read and write directly from an io.Reader / io.Writer without first buffering the whole document.

Common tags

| Tag | Effect | | --------------------- | ----------------------------------------------------------- | | json:"name" | Use this JSON key. | | json:"name,omitempty" | Skip the field if it's the zero value. | | json:"-" | Never encode or decode this field. | | json:",string" | Encode this number as a JSON string (useful for big ints). |

Strict decoding

By default, unknown JSON fields are silently dropped. To catch typos in incoming data, call DisallowUnknownFields:

dec := json.NewDecoder(r)
dec.DisallowUnknownFields()
if err := dec.Decode(&v); err != nil { return err }

For configs and APIs you control, this catches mistakes early.

Why does `json.Marshal({name: "Ada"})` only produce `{}` when `name` is lowercase in the Go struct?