跳转到主要内容
模块 5 · 第 4 课(共 5)课程中的24/50~12 min
模块课程(4/5)

字段标签和 JSON

结构体字段上的标签是元数据字符串,通过反射读取 通过 encoding/json、encoding/xml、验证器、ORM 等库。他们 写在字段类型后面的反引号(原始字符串)之间。

句法

Go
type User struct {
    Name string `json:"nome"`
    Age  int    `json:"eta,omitempty"`
}

格式约定:key:"value" 以空格分隔(NOT 逗号)用于多个键:

Go
type User struct {
    Email string `json:"email" validate:"required,email"`
}

json 标签:选项

最常见的选项是 json,由 encoding/json 使用:

标签效果
json:"nome"在 JSON 输出中将字段重命名为 nome
json:"nome,omitempty"如果该字段为零值,则忽略该字段
json:"-"不要序列化/反序列化该字段
json:",omitempty"json:",omitempty"保留 Go 字段名称,但带有 omitempty
Go
type User struct {
    Name     string `json:"nome"`
    Age      int    `json:"eta,omitempty"`
    Password string `json:"-"`
}

u := User{Name: "Ada", Age: 0, Password: "segreto"}
b, _ := json.Marshal(u)
fmt.Println(string(b))   // {"nome":"Ada"}

Age 被省略(零值 0 + omitempty); Password 是 完全排除。

元帅和元帅

Go
// struct -> JSON
b, err := json.Marshal(u)

// JSON -> struct (needs a POINTER)
var u2 User
err = json.Unmarshal(b, &u2)

Unmarshal 只接受一个指针,因为它必须写入 值的字段。

其他常见标签

  • xml:"..." — encoding/xml
  • yaml:"..." — yaml.v3
  • db:"..." — sqlx / pgx
  • validate:"..." — go-playground/验证器
  • form:"..." — gin / echo 绑定

库通过反射读取它们(reflect.StructTag.Get("json")): 在有人解释它们之前它们只是字符串。

尝试一下

锻炼#go.m5.l4.e1
尝试:0加载中...

将 json:"nome" 标签添加到 Name 字段,将 json:"eta" 标签添加到 Age 字段。

正在加载编辑器...
显示提示

标签是字段类型后面反引号之间的原始字符串。

3 次尝试后可用的解决方案

锻炼#go.m5.l4.e2
尝试:0加载中...

在 Age 字段中添加 omitempty 选项:当为 0 时必须省略。

正在加载编辑器...
显示提示

选项位于名称后面,以逗号分隔:json:"nome,omitempty"。

3 次尝试后可用的解决方案

Quiz#go.m5.l4.e3
准备好

它用标签 json:"nome" 和 json:"eta" 打印什么?

Go
u := User{Name: "Ada", Age: 36}
b, _ := json.Marshal(u)
fmt.Println(string(b))
答案选项

回顾

  • 标签是反引号之间的原始字符串:`key:"value" key2:"value2"`.
  • json:"nome": rename. omitempty: omit if zero value. -: exclude.
  • NON-exported (lowercase) fields are ignored by encoding/json.
  • json.Marshal(v) ↔ json.Unmarshal(数据, &v) (pointer).
  • Same mechanism for xml, yaml, db, validate, form, …