Beyond `omitempty`: Understanding `omitzero` in Go 1.24

Preface In Go version 1.24, the encoding/json package introduced the omitzero tag, making the behavior of ignoring zero-value fields more explicit and customizable. This article provides a detailed explanation of how to use the omitzero tag. The omitzero Tag The omitzero tag is used to control which zero-value fields should be omitted when serializing Go objects into JSON. Unlike the omitempty tag, which omits empty-value fields, zero values and empty values, while similar, are not equivalent in Go. For example: For the time.Time type, the zero value is "0001-01-01T00:00:00Z", which is not considered an empty value. For a slice field like IntSlice []int, both [] and nil are considered empty values. Why Use omitzero Precise control: Explicitly omits zero-value fields, rather than empty-value fields. Custom control: By implementing the IsZero() bool method, you can define custom logic for determining a field’s zero value. Using the omitzero Tag package main import ( "encoding/json" "fmt" "time" ) type User struct { Name string `json:"name,omitzero"` Age int `json:"age,omitzero"` Hobbies []string `json:"hobbies,omitzero"` BornAt time.Time `json:"born_at,omitzero"` } func main() { user := User{ Name: "Leapcell", Age: 18, Hobbies: []string{}, } bytes, _ := json.MarshalIndent(user, "", " ") fmt.Println(string(bytes)) } Running string(bytes) will output the following JSON result: { "name": "Leapcell", "age": 18, "hobbies": [] } If the omitempty tag were used instead, the hobbies field would be omitted. Furthermore, even if born_at is a zero value, it would still be serialized as "born_at": "0001-01-01T00:00:00Z". By using the omitzero tag, we can more precisely control which fields are ignored, ensuring that only zero-value fields are excluded. The IsZero() bool Method The IsZero() bool method is used to customize the logic for determining whether a field is a zero value. If you want to change how a field’s zero value is determined, you can implement the IsZero method for that field. Here's an example: package main import ( "encoding/json" "fmt" "time" ) type Age int func (age *Age) IsZero() bool { return *age

May 9, 2025 - 20:37
 0
Beyond `omitempty`: Understanding `omitzero` in Go 1.24

Cover

Preface

In Go version 1.24, the encoding/json package introduced the omitzero tag, making the behavior of ignoring zero-value fields more explicit and customizable. This article provides a detailed explanation of how to use the omitzero tag.

The omitzero Tag

The omitzero tag is used to control which zero-value fields should be omitted when serializing Go objects into JSON. Unlike the omitempty tag, which omits empty-value fields, zero values and empty values, while similar, are not equivalent in Go. For example:

  • For the time.Time type, the zero value is "0001-01-01T00:00:00Z", which is not considered an empty value.
  • For a slice field like IntSlice []int, both [] and nil are considered empty values.

Why Use omitzero

  • Precise control: Explicitly omits zero-value fields, rather than empty-value fields.
  • Custom control: By implementing the IsZero() bool method, you can define custom logic for determining a field’s zero value.

Using the omitzero Tag

package main

import (
  "encoding/json"
  "fmt"
  "time"
)

type User struct {
  Name    string    `json:"name,omitzero"`
  Age     int       `json:"age,omitzero"`
  Hobbies []string  `json:"hobbies,omitzero"`
  BornAt  time.Time `json:"born_at,omitzero"`
}

func main() {
  user := User{
    Name:    "Leapcell",
    Age:     18,
    Hobbies: []string{},
  }

  bytes, _ := json.MarshalIndent(user, "", "  ")
  fmt.Println(string(bytes))
}

Running string(bytes) will output the following JSON result:

{
  "name": "Leapcell",
  "age": 18,
  "hobbies": []
}

If the omitempty tag were used instead, the hobbies field would be omitted. Furthermore, even if born_at is a zero value, it would still be serialized as "born_at": "0001-01-01T00:00:00Z". By using the omitzero tag, we can more precisely control which fields are ignored, ensuring that only zero-value fields are excluded.

The IsZero() bool Method

The IsZero() bool method is used to customize the logic for determining whether a field is a zero value. If you want to change how a field’s zero value is determined, you can implement the IsZero method for that field. Here's an example:

package main

import (
  "encoding/json"
  "fmt"
  "time"
)

type Age int

func (age *Age) IsZero() bool {
  return *age <= 0
}

type User struct {
  Name    string    `json:"name,omitzero"`
  Age     Age       `json:"age,omitzero"`
  Hobbies []string  `json:"hobbies,omitzero"`
  BornAt  time.Time `json:"born_at,omitzero"`
}

func main() {
  user := User{
    Name:    "Leapcell",
    Age:     -1,
    Hobbies: []string{},
  }

  bytes, _ := json.MarshalIndent(user, "", "  ")
  fmt.Println(string(bytes))
}

In this example, the Age field defines its own zero-value logic by implementing the IsZero method. If Age is less than or equal to 0, IsZero returns true, and the field will be omitted during serialization. The output will be:

{
  "name": "Leapcell",
  "hobbies": []
}

Summary

In Go, by using the omitzero tag, we can precisely control which fields are omitted during JSON serialization, ensuring that only zero-value fields are excluded. Additionally, by implementing the IsZero method, we can define custom zero-value logic for specific fields, enabling more flexible and context-aware serialization behavior.

We are Leapcell, your top choice for hosting Go projects.

Leapcell

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!

Try Leapcell

Follow us on X: @LeapcellHQ

Read on our blog