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).
omitemptyomits false, 0, nil pointer/interface, and empty slices/maps/strings (so[]string{}is omitted too).omitemptynever omits structs —addrand a zerotime.Timewould still appear. That's why Go 1.24 addedomitzero, which omits the zero value of any type and honors anIsZero() boolmethod (so zerotime.Timeis dropped).,stringencodes 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
- Q449How is context used in net/http on both server and client sides? What happens when a client disconnects mid-request?
- Q450What does this handler send to the client, and why?
- Q452What does this print? How do you preserve large integer precision when decoding unknown JSON?
- Q453You implemented MarshalJSON but it isn't called. Why? Explain receiver rules and the recursion trap.
- Q454json.Unmarshal vs json.Decoder: when to use each, and how do you safely decode a request body?
- Q455What does this print? (nil vs empty slices and maps in JSON)