go中json编解码需确保结构体字段首字母大写(导出),否则静默忽略;json.unmarshal必须传指针,omitempty慎用于数值字段,嵌套或动态结构宜用json.rawmessage或map[string]interface{}。

Go 里 JSON 编解码不是调用 json.Marshal 和 json.Unmarshal 就完事了——字段导出、标签写法、零值处理、嵌套结构、错误传播,每一步都可能 silently 失败。
结构体字段必须首字母大写才能被序列化
小写字母开头的字段(如 name string)在 json.Marshal 时会被忽略,输出为空对象 {} 或缺失字段,且不报错。这是最常被忽略的隐性陷阱。
- 必须使用导出字段:改
name为Name - 标签中的键名可保持小写,不影响序列化结果:
`json:"name"` - 如果结构体来自第三方包且字段不可改,只能用
map[string]interface{}中转
json.Unmarshal 要传指针,否则值不会写入
调用 json.Unmarshal(data, v) 时,v 必须是指向目标变量的指针。传值会导致解析成功但结构体字段仍是零值,比如 Age 保持 0、Name 保持空字符串。
- 正确写法:
err := json.Unmarshal(data, &p) - 错误写法:
err := json.Unmarshal(data, p)(编译通过但逻辑失效) - 对切片反序列化也一样:
var users []User; json.Unmarshal(data, &users)
omitempty 标签会跳过零值,但可能掩盖业务逻辑问题
omitempty 在序列化时跳过字段值为零值(""、0、false、nil)的字段,但它不区分“用户没填”和“用户明确填了 0”。例如年龄为 0 的婴儿、金额为 0 的退款单,都会被丢弃。
- 慎用于数值型字段,除非业务上 0 确实等价于“未提供”
- 想保留字段但省略空字符串?用
string+ 自定义MarshalJSON方法 - 时间字段别直接加
omitempty,time.Time{}是零值,会丢失
嵌套结构或动态字段要用 json.RawMessage 或 map[string]interface{}
当 JSON 结构不确定(比如 API 返回的 data 字段可能是对象、数组或 null),直接反序列化到固定结构体会 panic 或静默失败。
- 先用
json.RawMessage延迟解析:Data json.RawMessage `json:"data"` - 再根据
len(Data) > 0和首字符判断类型,按需json.Unmarshal -
map[string]interface{}灵活但无类型安全,嵌套深时类型断言易出错,建议仅用于顶层路由分发
真正难的不是语法,是搞清“这个字段到底有没有被序列化进去”——打印 len(jsonData) 比猜更可靠;反序列化后立刻检查关键字段是否仍为零值,比依赖文档更实在。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











