Go

Explain encoding/json struct tag behavior: omitempty, omitzero, "-", and ",string". What does this print?

Question 451HardGo 1.22 to 1.25
type Addr struct{ City string }

type User struct {
	Name     string    `json:"name"`
	password string    // unexported
	Age      int       `json:"age,omitempty"`
	Tags     []string  `json:"tags,omitempty"`
	Addr     Addr      `json:"addr,omitempty"`
	Created  time.Time `json:"created,omitzero"`
	ID       int64     `json:"id,string"`
	Secret   string    `json:"-"`
}

b, _ := json.Marshal(User{Name: "a", password: "x", Tags: []string{}, ID: 7, Secret: "s"})
fmt.Println(string(b))

Output: {"name":"a","addr":{"City":""},"id":"7"}

  • Unexported fields are always skipped (reflection cannot read them).
  • omitempty omits false, 0, nil pointer/interface, and empty slices/maps/strings (so []string{} is omitted too).
  • omitempty never omits structs — addr and a zero time.Time would still appear. That's why Go 1.24 added omitzero, which omits the zero value of any type and honors an IsZero() bool method (so zero time.Time is dropped).
  • ,string encodes numbers/bools as JSON strings — useful for int64 IDs consumed by JavaScript (53-bit float precision).
  • "-" always skips; "-," names the key literally -.

Without a tag, the key is the Go field name; unmarshaling matches keys case-insensitively, a frequent source of surprise.

More on Standard Library, HTTP & Systems Design in Go

All 35 Standard Library, HTTP & Systems Design in Go questions