Understanding the `omitempty` Tag in Go's JSON Encoding
James Reed
Infrastructure Engineer · Leapcell

Key Takeaways
- The
omitempty
tag omits fields from JSON output when they hold empty values. - Structs must be pointers to be omitted when empty.
- Zero values may be omitted unintentionally, affecting data completeness.
In Go, struct field tags provide powerful options to customize JSON encoding and decoding. One commonly used tag is omitempty
, which instructs the JSON encoder to omit a field from the output if its value is empty. Understanding how omitempty
works is essential for effective JSON handling in Go.
What Does omitempty
Do?
The omitempty
tag tells the JSON encoder to exclude a struct field from the JSON output if the field's value is considered empty. In Go, a value is deemed empty if it is:
false
for boolean types0
for numeric types""
for stringsnil
for pointers, interfaces, maps, slices, and channels- An array, slice, or map of length zero
For example:
type Example struct { Name string `json:"name,omitempty"` Age int `json:"age,omitempty"` Email string `json:"email,omitempty"` }
If an Example
struct has Age
set to 0
and Email
set to an empty string, those fields will be omitted from the JSON output.
Basic Usage
Consider the following struct:
type Dog struct { Breed string `json:"breed"` WeightKg int `json:"weight_kg,omitempty"` }
When encoding an instance of Dog
where WeightKg
is 0
, the JSON output will exclude the weight_kg
field:
d := Dog{ Breed: "pug", } b, _ := json.Marshal(d) fmt.Println(string(b)) // Output: {"breed":"pug"}
Here, WeightKg
is omitted because its zero value (0
) is considered empty.
omitempty
with Nested Structs
The omitempty
tag does not automatically omit nested structs, even if all their fields are empty. For instance:
type Dimensions struct { Height int `json:"height,omitempty"` Width int `json:"width,omitempty"` } type Dog struct { Breed string `json:"breed"` WeightKg int `json:"weight_kg,omitempty"` Size Dimensions `json:"size,omitempty"` }
If Size
is an empty Dimensions
struct, it will still appear in the JSON output:
d := Dog{ Breed: "pug", } b, _ := json.Marshal(d) fmt.Println(string(b)) // Output: {"breed":"pug","size":{"height":0,"width":0}}
To omit Size
when it has zero values, define it as a pointer:
type Dog struct { Breed string `json:"breed"` WeightKg int `json:"weight_kg,omitempty"` Size *Dimensions `json:"size,omitempty"` }
Now, if Size
is nil
, it will be omitted:
d := Dog{ Breed: "pug", } b, _ := json.Marshal(d) fmt.Println(string(b)) // Output: {"breed":"pug"}
Special Considerations
Zero Values vs. Omitted Fields
Using omitempty
can lead to situations where fields with zero values are omitted, which might not always be desirable. For example:
type Restaurant struct { NumberOfCustomers int `json:"number_of_customers,omitempty"` Name string `json:"name"` } r := Restaurant{ Name: "Diner", } b, _ := json.Marshal(r) fmt.Println(string(b)) // Output: {"name":"Diner"}
Here, NumberOfCustomers
is omitted because its zero value (0
) is considered empty. If you want to include fields with zero values, avoid using omitempty
for those fields.
Handling time.Time
Fields
The time.Time
type is a struct, and its zero value (time.Time{}
) is not considered empty by omitempty
. To omit time.Time
fields when they are zero, define them as pointers:
type Event struct { Name string `json:"name"` Timestamp *time.Time `json:"timestamp,omitempty"` }
If Timestamp
is nil
, it will be omitted from the JSON output.
Conclusion
The omitempty
tag is a useful tool in Go's JSON encoding, allowing for cleaner JSON output by excluding fields with empty values. However, it's crucial to understand what Go considers empty for different types and to be mindful of how omitempty
interacts with nested structs and zero values. By leveraging omitempty
appropriately, you can ensure your JSON serialization aligns with your application's requirements.
For more detailed information, refer to the official Go documentation on the encoding/json
package and community discussions on this topic.
FAQs
Zero values like 0
, false
, ""
, nil
pointers, empty slices, and empty maps.
Non-pointer structs are never considered nil
, so they are not omitted.
Use a *time.Time
pointer and set it to nil
when not needed.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ