Searches for golang json omitempty, golang omitempty, go json omitempty, json omitempty, omitempty golang, omitempty json golang, go omitempty, omitempty, and omitempty meaning all point at the same encoding/json rule: omitempty skips a field when its Go value is “empty” under the encoder’s definition. A frequent surprise—captured by queries like omitempty has no effect on nested struct fields—is that a non-pointer nested struct is still a real value: it marshals as {}, so the outer key is usually not omitted. This guide spells out omitempty behavior, that nested-struct pitfall, and safer patterns. For broader JSON workflows, see parse JSON in Go and struct tags.
Tested with Go 1.24 on Linux.
What omitempty does
In a struct tag such as `json:"name,omitempty"`, the word omitempty is handled by encoding/json. When marshaling, if the field’s value counts as empty, the field is left out of the JSON object. When unmarshaling, omitted keys simply leave the field at its zero value.
Simple fields: strings, numbers, and booleans
Zero values—"" for string, 0 for numeric types, false for bool—are empty for omitempty, so they disappear from output:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
}
func main() {
b, _ := json.Marshal(&Person{Name: ""})
fmt.Println(string(b))
}Running the program prints {}, because both fields are at their zero values.
Slices, maps, and pointers
nil or empty slices and maps count as empty. A nil pointer is also empty, which is the usual way to represent “this object was not set”:
package main
import (
"encoding/json"
"fmt"
)
type Order struct {
Items []string `json:"items,omitempty"`
Meta map[string]string `json:"meta,omitempty"`
}
func main() {
b, _ := json.Marshal(&Order{})
fmt.Println(string(b))
}Output is {}.
Nested structs: value vs pointer (the common gotcha)
Non-pointer nested struct
A nested value struct is never nil. Its zero value is “a struct whose fields are zero,” which still encodes as a JSON object. omitempty on the outer field therefore does not remove the key—you often see {"address":{}}, which matches searches claiming omitempty has no effect on nested struct fields (for dropping the whole block):
package main
import (
"encoding/json"
"fmt"
)
type Address struct {
City string `json:"city,omitempty"`
State string `json:"state,omitempty"`
}
type User struct {
Name string `json:"name,omitempty"`
Address Address `json:"address,omitempty"` // value, not pointer
}
func main() {
b, _ := json.Marshal(&User{})
fmt.Println(string(b))
}{"address":{}}Inner omitempty tags still omit zero inner fields, but the address key remains because the struct value is not considered empty at the outer level.
Pointer to nested struct
Use a pointer when the whole nested object is optional. A nil pointer is empty, so the key disappears:
package main
import (
"encoding/json"
"fmt"
)
type Address struct {
City string `json:"city,omitempty"`
}
type User struct {
Name string `json:"name,omitempty"`
Address *Address `json:"address,omitempty"`
}
func main() {
b, _ := json.Marshal(&User{})
fmt.Println(string(b))
}{}That pattern is the standard fix when you truly need golang json omitempty semantics for optional nested documents.
Booleans and meaningful zeros
omitempty on a bool omits false, which is wrong when clients must distinguish “false” from “field not sent”. Use a pointer *bool, drop omitempty, or marshal with a custom type.
Quick test with the standard library
You do not need external assertion libraries to sanity-check output:
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
type sample struct {
Field string `json:"field,omitempty"`
}
with, _ := json.Marshal(sample{Field: "value"})
without, _ := json.Marshal(sample{})
fmt.Println(strings.Contains(string(with), "value"))
fmt.Println(strings.Contains(string(without), "field"))
}Running it prints true then false.
Summary
Golang omitempty and go json omitempty mean: omit the JSON key when the Go field is the type’s zero value (plus nil pointers and empty collections). Omitempty meaning for APIs is “hide zero defaults.” For nested struct fields, remember that a value nested struct encodes as {}, so omitempty usually does not remove the outer key—that is why people say omitempty has no effect on nested struct fields in that sense. Prefer *T with nil, json.Marshaler, or explicit types when you need finer control than the default rules.

