头图

前言

Go 1.24 版本中,encoding/json 包新增了 omitzero 标签,使得零值字段的忽略行为更加明确和可定制。本文将详细介绍 omitzero 标签的使用。

准备好了吗?准备一杯你最喜欢的咖啡或茶,随着本文一探究竟吧。

omitzero 标签

omitzero 标签用于在将 Go 对象序列化为 JSON 时,控制哪些 零值 字段应被忽略。与 omitempty 标签不同,omitempty 忽略的是 空值 字段,而 零值空值 虽然相似,但在 Go 中并不等价。例如:

  • 对于 time.Time 类型,零值是 "0001-01-01T00:00:00Z",这并不被视为 空值
  • 对于切片字段 IntSlice []int,当其值为 []nil 时,都会被视为 空值

为什么使用 omitzero

  • 精准控制:明确地忽略零值字段,而不是空值字段。
  • 定制化控制:通过 IsZero() bool 方法,可以自定义字段的零值判断逻辑。

omitzero 标签的使用

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:    "陈明勇",
        Age:     18,
        Hobbies: []string{},
    }

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

打印 string(bytes) 将会输出以下 json 结果:

{
  "name": "陈明勇",
  "age": 18,
  "hobbies": []
}

如果使用 omitempty 标签,hobbies 字段将被省略,而即使 born_at 是零值,依然会被序列化成 "born_at": "0001-01-01T00:00:00Z"。通过使用 omitzero 标签,我们可以更精确地控制哪些字段会被忽略,确保只有零值字段才会被排除。

IsZero() bool 方法

IsZero() bool 方法用于自定义字段的零值判断逻辑。如果你希望修改某个字段的零值的判定方式,可以为该字段实现 IsZero 方法。下面是一个示例:

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:    "陈明勇",
        Age:     -1,
        Hobbies: []string{},
    }

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

在这个示例中,Age 字段通过实现 IsZero 方法来控制其零值判断逻辑。如果 Age 小于等于 0 时,IsZero 返回 true,该字段就会被忽略。输出结果为:

{
  "name": "陈明勇",
  "hobbies": []
}

小结

Go 语言中,通过使用 omitzero 标签,我们可以精确控制哪些字段被忽略,确保只有零值字段会被排除。同时,通过实现 IsZero 方法,我们可以自定义字段的零值判断逻辑,以满足不同的序列化需求。

推荐阅读

Go 1.24.0 重磅发布:新特性、新工具,开发者必看!

Go 1.24 新特性:泛型类型别名,让代码变得更灵活、更清晰


你好,我是陈明勇,一名热爱技术、乐于分享的开发者,同时也是开源爱好者。

成功的路上并不拥挤,有没有兴趣结个伴?

关注我,加我好友,一起学习一起进步!


陈明勇
29 声望6 粉丝

一个热爱技术,喜欢专研技术的程序员。