Lesson 19 / 26
JSON With Struct Tags
Marshal and unmarshal safely.
Tags control field names and omission
encoding/json maps exported struct fields to JSON. Struct tags set names (json:"customer"), skip empty values (omitempty), or exclude fields (json:"-"); unexported fields are always ignored. Unknown JSON keys are ignored by default (use a Decoder with DisallowUnknownFields to reject them), and type mismatches return descriptive errors. Validate decoded data before using it.
Tags, ignored fields and a type error, run
I ran this with Go 1.27.1 (go run . in a module named demo, standard library only). Marshalling omits empty Items, the "-" tagged Notes and the unexported field. Unmarshalling ignores the unknown "extra" key; a string for the numeric id returns a clear error.
package main
import (
"encoding/json"
"fmt"
)
type Order struct {
ID int `json:"id"`
Customer string `json:"customer"`
Items []string `json:"items,omitempty"`
Notes string `json:"-"` // never serialised
internal string // unexported: ignored by encoding/json
}
func main() {
o := Order{ID: 7, Customer: "Asha", Notes: "secret", internal: "x"}
b, _ := json.Marshal(o)
fmt.Println(string(b))
var in Order
err := json.Unmarshal([]byte(`{"id": 8, "customer": "Ravi", "items": ["pen"], "extra": true}`), &in)
fmt.Printf("%+v err=%v\n", in, err)
err = json.Unmarshal([]byte(`{"id": "eight"}`), &in)
fmt.Println("type error:", err)
}
Output:
{"id":7,"customer":"Asha"}
{ID:8 Customer:Ravi Items:[pen] Notes: internal:} err=<nil>
type error: json: cannot unmarshal string into Go struct field Order.id of type intReject unknown fields in APIs
For request bodies, a json.Decoder with DisallowUnknownFields catches typos in client payloads.
Quick check: What does the tag json:"-" do?
- Encrypts it
- Makes the field required
- Renames it to "-"
- Excludes the field from JSON encoding and decoding
Answer
Excludes the field from JSON encoding and decoding — Keep internal fields out of payloads.