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)
  • nil pointers 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 false should be omitted
  • Non‑pointer numeric types where 0 should be omitted
  • Struct values where the zero value should be omitted
  • time.Time values where time.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 for json_omitzero at line 20, establishing the official rule: "Use omitzero on JSON‑tagged bool, numeric, struct, and time fields whose zero value should be omitted; keep omitempty for 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 the omitzero rule is available to automated tooling.

Summary

  • omitempty is the standard Go tag for omitting empty strings, slices, maps, and nil pointers.
  • omitzero is the JetBrains guideline extension for omitting zero values of non‑pointer booleans, numerics, structs, and time.Time fields.
  • Do not use omitzero for strings, slices, or maps—continue using omitempty for those types.
  • Combine both tags on pointer fields when you need to omit both nil pointers and zero values pointed to by non‑nil pointers.
  • Reference internal/guidelines/guidelines_test.go for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →