go结构体json序列化默认用大驼峰字段名,需通过json tag显式指定小写下划线风格;空tag忽略字段,omitempty跳过零值,嵌套结构需手动标注,匿名字段不继承tag,自定义序列化用marshaljson方法。

JSON序列化时字段名不按预期小写或驼峰?用json标签控制
Go 默认用结构体字段名(大写首字母)作为 JSON 键,但多数 API 要求小写或 camelCase。直接改字段名会破坏 Go 的导出规则,所以必须靠 json 标签。
- 字段名后加
json:"field_name"强制指定键名,比如UserName string `json:"user_name"` - 加
omitempty可跳过零值字段:Age int `json:"age,omitempty"`,空字符串、0、nil 切片等都不输出 - 想忽略某个字段,用
-:Password string `json:"-"` - 注意:标签里的引号必须是英文双引号,且不能有空格 ——
json:"name,omitempty"✅,json: "name"❌
需要动态控制字段是否序列化?重写MarshalJSON方法
当字段是否输出取决于运行时状态(比如权限、开关配置),json 标签不够用,得自定义序列化逻辑。
- 实现
MarshalJSON() ([]byte, error)方法,返回你构造的map[string]interface{}或手动拼接的 JSON 字节 - 避免在该方法里直接调用
json.Marshal原结构体,否则可能无限递归 - 常见写法是先转成 map,删掉不该出现的 key,再 marshal:
func (u User) MarshalJSON() ([]byte, error) { m := map[string]interface{}{ "id": u.ID, "name": u.Name, } if u.IncludeEmail { m["email"] = u.Email } return json.Marshal(m) }
想统一处理所有结构体的时间、数字、枚举字段格式?用自定义类型+MarshalJSON
重复给每个 time.Time 字段加 json:"xxx,string" 很麻烦,也不够灵活。更优雅的方式是封装类型。
用于端到端视频本地化流程的轻量编排器,路由至四个专注子技能——/wjs-transcribing-audio、/wjs-translating-subtitles...
- 定义新类型如
type ISOTime time.Time,然后为它实现MarshalJSON()返回"2024-03-15T10:30:00Z" - 数字类型同理:比如
type Amount float64,MarshalJSON输出带两位小数的字符串,避免浮点精度问题 - 枚举值常用
int或string底层,但对外暴露语义化字符串(如"active"而非1),也靠这个机制 - 注意:别忘了同时实现
UnmarshalJSON,否则反序列化会失败
第三方库能简化吗?easyjson 和 ffjson 不解决字段定制问题
这些库主要优化性能(生成静态 marshal 代码),但字段名控制、条件序列化、类型格式化等逻辑仍得自己写,和标准 encoding/json 一致。
- 它们不改变
json标签行为,也不自动帮你做运行时判断 - 如果你只是想让时间字段默认输出 ISO8601,还是得靠自定义类型 +
MarshalJSON - 真正省事的方案不是换库,而是把常用格式封装成可复用类型,比如
type FormattedTime time.Time放在 utils 包里
最易被忽略的是:自定义 MarshalJSON 后,如果结构体嵌套了该类型字段,父结构体不会自动继承其序列化逻辑 —— 必须确保嵌套字段本身也用了该类型,而不是原生 time.Time 或 int。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










