go 的 json.marshal 不自动转换字段名,必须用 json:"xxx" tag 显式指定小写下划线格式;小写字段不导出,会被忽略;嵌套结构体、切片、map 等均需逐字段打 tag;omitempty 按零值过滤,"-" 屏蔽字段;复杂逻辑需实现 marshaljson 方法。

Go 默认不会把结构体字段名转成小写下划线风格,必须显式用 json tag 控制;不加 tag 就按 Go 字段名(大驼峰)输出,加了空 tag json:"" 会直接丢掉该字段。
结构体字段名怎么变成 user_name 这种格式
Go 的 json.Marshal 不做自动命名转换,它只认 struct tag。你写 ID int,默认输出就是 "ID": 1,不是 "id",更不是 "user_id"。
要改成下划线风格,每个字段都得手动加 json tag:
type User struct {
ID int `json:"id"`
UserName string `json:"user_name"`
Email string `json:"email,omitempty"`
}
-
json:"id"把ID映射为id;json:"user_name"把UserName映射为user_name -
omitempty表示值为零值时跳过该字段:空字符串、0、nil 切片等都不会出现在输出里 - 字段名首字母必须大写(导出),否则
json包根本看不到它——小写字段如userName或email会被忽略,输出为空对象{}
嵌套结构体的 JSON tag 容易漏打
嵌套结构体不会继承外层的命名规则,每个字段都要单独标 json tag。比如 User 里有个 Address 字段,不能只给 User.Address 加 tag,而要进到 Address 结构体内部一个个标:
type Address struct {
City string `json:"city"`
Zip string `json:"zip_code"`
}
type User struct {
ID int `json:"id"`
Address Address `json:"address"`
}
- 如果
Address里没打 tag,那它的字段就按 Go 名输出(City→"City"),不是你想要的"city" - 匿名字段(如
Address直接嵌入)也不会自动包装进一个 key,而是把它的字段平铺到顶层,且仍依赖各自 tag - 想让整个
Address块变成"shipping_address"?那就得在User里定义新字段:ShippingAddress Address `json:"shipping_address"`,而不是给匿名字段加别名 tag
切片、map 和敏感字段怎么控制输出
数组和 map 字段一样要打 tag,比如 Tags []string `json:"tags"`。但真正容易出问题的是字段过滤:
- 用
json:"-"彻底屏蔽字段(如密码、内部 ID):Password string `json:"-"` -
omitempty看的是“零值”,不是“空字符串”:对int是0,对bool是false,对指针是nil——别误以为"0"或"false"字符串也会被跳过 - 如果要动态控制(比如只在特定角色下返回邮箱),就不能靠 tag,得实现
MarshalJSON方法自己拼 JSON 字节
什么时候必须自己写 MarshalJSON
tag 解决不了所有问题。比如要扁平化嵌入字段、按固定顺序输出键、或把 []string 转成逗号分隔字符串,就得实现 MarshalJSON 方法:
func (u User) MarshalJSON() ([]byte, error) {
type Alias User // 防止无限递归
return json.Marshal(&struct {
*Alias
FullName string `json:"full_name"`
}{
Alias: (*Alias)(&u),
FullName: u.FirstName + " " + u.LastName,
})
}
- 自定义方法里可以自由组合字段、改类型、加逻辑,但要注意避免循环调用
json.Marshal(u) - 若结构体含
interface{}或运行时才确定类型的字段(如[]interface{}),tag 失效,只能走MarshalJSON - 性能上,纯 tag 最快;一旦用反射或手动拼接,就要多一次内存分配和字符串操作
最常被忽略的一点:字段导出性(首字母大写)比 tag 优先级还高。tag 写得再对,字段小写就等于不存在。调试时看到空 {},第一反应不该是 tag 写错了,而是检查字段名是不是全小写。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











