How to Use `omitzero` vs `omitempty` in Go JSON Struct Tags: Complete Guide
Use omitzero for non‑pointer boolean, numeric, struct, and time.Time fields to omit their zero values, while reserving standard omitempty for strings, slices, and maps where you want to drop empty collections.
The JetBrains go‑modern‑guidelines repository introduces omitzero as a complementary struct tag to the standard omitempty option. Understanding when to apply each tag ensures your JSON output excludes unwanted zero values without accidentally dropping legitimate empty collections. This guide explains the exact differences and implementation details based on the official JetBrains guidelines source code.
Understanding the Standard omitempty Tag
The omitempty option is native to Go's encoding/json package. It instructs the encoder to skip a field when its value is considered "empty" according to specific rules in the standard library.
The standard omitempty behavior omits fields containing:
- Empty strings (
"") - Zero‑length slices or maps (
len == 0) nilpointers or interfaces- Zero values for booleans (
false) and numeric types (0) only if the field is a pointer
Understanding the Custom omitzero Tag
According to the JetBrains Go Modern Guidelines, omitzero is a guideline‑specific tag used for JSON‑tagged fields whose zero value should always be omitted, regardless of type. As defined in internal/guidelines/guidelines_test.go, this tag addresses limitations in the standard omitempty behavior.
Use omitzero specifically for:
- Non‑pointer booleans where
falseshould be omitted - Non‑pointer numeric types where
0should be omitted - Struct values where the zero value should be omitted
time.Timevalues wheretime.Time{}should be omitted
Importantly, omitzero does not replace omitempty for strings, slices, or maps. Those types should continue to use omitempty to drop empty collections or strings.
When to Use omitzero vs omitempty
Choose your struct tag based on the field type and desired omission behavior:
| Field Type | Recommended Tag | Reason |
|---|---|---|
string |
omitempty |
Omits only empty strings ("") |
Slices ([]T) |
omitempty |
Omits nil or zero‑length slices |
Maps (map[K]V) |
omitempty |
Omits nil or zero‑length maps |
bool (non‑pointer) |
omitzero |
Omits false values |
| Numeric types (non‑pointer) | omitzero |
Omits zero values (0) |
time.Time |
omitzero |
Omits zero time (time.Time{}) |
| Structs | omitzero |
Omits zero value structs |
| Pointers | omitempty (or both) |
omitempty handles nil; combine with omitzero to also omit pointed‑to zero values |
Practical Implementation Examples
The following struct definition from the JetBrains guidelines demonstrates proper usage of both tags:
type Example struct {
// Zero boolean omitted by omitzero
Active bool `json:"active,omitzero"`
// Zero int omitted by omitzero
Count int `json:"count,omitzero"`
// Zero time omitted by omitzero
Created time.Time `json:"created,omitzero"`
// Empty string omitted by omitempty (standard)
Name string `json:"name,omitempty"`
// Empty slice omitted by omitempty (standard)
Items []string `json:"items,omitempty"`
// Pointer field – zero value omitted automatically when nil,
// but if you want to treat the pointed value's zero as omitted,
// combine both tags:
Score *int `json:"score,omitzero,omitempty"`
}
When encoding instances of this struct using json.Marshal, the output varies based on the field values:
| Field | Input Value | Output JSON |
|---|---|---|
Active |
false (zero) |
omitted |
Count |
0 (zero) |
omitted |
Created |
time.Time{} (zero) |
omitted |
Name |
"" (empty) |
omitted |
Items |
nil or [] |
omitted |
Score |
nil pointer |
omitted |
Score |
Pointer to 0 |
omitted (zero int inside pointer) |
Source Code Reference
These tagging rules are formally defined and enforced within the JetBrains go‑modern‑guidelines repository:
-
internal/guidelines/guidelines_test.go– Contains the canonical guideline description forjson_omitzeroat line 20, establishing the official rule: "Useomitzeroon JSON‑tagged bool, numeric, struct, and time fields whose zero value should be omitted; keepomitemptyfor empty strings, slices, and maps." -
internal/guidelines/guidelines.go– Loads and provides the guidelines data used by the CLI tooling and documentation generators. -
internal/guidelines/schema/schema.go– Parses the JSON representation of guidelines, ensuring theomitzerorule is available to automated tooling.
Summary
omitemptyis the standard Go tag for omitting empty strings, slices, maps, and nil pointers.omitzerois the JetBrains guideline extension for omitting zero values of non‑pointer booleans, numerics, structs, andtime.Timefields.- Do not use
omitzerofor strings, slices, or maps—continue usingomitemptyfor those types. - Combine both tags on pointer fields when you need to omit both
nilpointers and zero values pointed to by non‑nil pointers. - Reference
internal/guidelines/guidelines_test.gofor the official rule definitions.
Frequently Asked Questions
What is the main difference between omitzero and omitempty?
omitempty is part of Go's standard library and only omits zero values for booleans and numerics when they are pointers, while always omitting empty strings and collections. omitzero is a JetBrains guideline convention that omits zero values for booleans, numerics, structs, and time.Time regardless of whether they are pointer types, but it is not used for strings or collections.
Can I use omitzero and omitempty together on the same field?
Yes. For pointer fields, combining both tags—such as json:"score,omitzero,omitempty"—ensures the field is omitted both when the pointer is nil (handled by omitempty) and when the pointer holds a zero value (handled by omitzero). This pattern is specifically recommended in the JetBrains guidelines for pointer fields.
Should I replace all my omitempty tags with omitzero?
No. The guidelines explicitly state that omitzero does not replace omitempty for strings, slices, or maps. You should continue using omitempty for those types to omit empty collections and strings, while reserving omitzero specifically for boolean, numeric, struct, and time fields where the zero value should be suppressed.
Where is the omitzero rule officially documented?
The official rule is documented in the internal/guidelines/guidelines_test.go file within the JetBrains go‑modern‑guidelines repository at line 20, where the test suite defines the expected behavior for JSON struct tags. The internal/guidelines/schema/schema.go file ensures this rule is parsed and available to guideline enforcement tools.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →