Understanding the `omitempty` Tag in Go's JSON Encoding
Wenhao Wang
Dev Intern · Leapcell

Key Takeaways
- The
omitemptytag 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:
falsefor boolean types0for numeric types""for stringsnilfor 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



