Go 的 encoding/json 默认不支持 nil 指针字段反序列化且无容错机制:导出字段需正确 json tag,小写字段被忽略;下划线 key 需显式 tag;nil 指针不自动初始化;数字默认 float64 易致 int64 解析失败;嵌套 null 值需用指针避免 panic;无宽松模式,须审慎定义 struct。

Go 的 encoding/json 标准库解析 JSON 时,**默认不支持 nil 指针字段的反序列化,也不自动处理类型不匹配或缺失字段的容错**——这意味着你写的 struct 字段名、tag、类型稍有偏差,json.Unmarshal 就会静默跳过或报错,而不是“尽力而为”。
struct 字段必须导出且带正确 json tag
Go 只能对首字母大写的导出字段进行 JSON 反序列化。如果字段小写(比如 name string),即使写了 `json:"name"`,json.Unmarshal 也完全忽略它。
常见错误场景:从 API 接收 JSON 后,struct 字段没加 json:"xxx" tag,或拼写不一致(如后端返回 "user_id",你写成 UserID int `json:"userId"`)。
- 字段名大小写必须匹配 JSON key,或靠
json:tag 显式映射 - 嵌套结构体字段也要导出,否则内层字段无法解析
- 如果 JSON key 是下划线风格(如
"created_at"),tag 必须写成`json:"created_at"`,不能依赖 Go 字段名自动转驼峰
nil 指针字段不会被自动初始化
如果你定义了 CreatedAt *time.Time 这样的指针字段,但 JSON 中该字段为 null 或缺失,json.Unmarshal 不会把指针设为 nil,也不会分配新值——它直接跳过,保持原值(可能是未初始化的 nil,也可能是个旧时间)。这容易导致空指针 panic 或逻辑错乱。
立即学习“go语言免费学习笔记(深入)”;
解决办法不是靠“默认行为”,而是显式控制:
- 用
omitempty配合指针字段,避免序列化时输出 null,但反序列化仍需小心 - 更稳妥的是用自定义类型 + 实现
UnmarshalJSON方法,对null做明确处理 - 或者改用值类型(如
CreatedAt time.Time)+ 配合time.Time的零值判断(但要注意零值是0001-01-01,不是空)
数字类型模糊导致解析失败
JSON 规范里没有 int/float 区分,所有数字都是“number”。Go 的 json.Unmarshal 默认把数字解析为 float64,除非目标字段是整型且值能无损表示为整数。一旦 JSON 里传了个超大整数(如 9223372036854775808),而你定义的是 int64,就可能触发 json: cannot unmarshal number into Go struct field xxx of type int64 错误。
这不是 bug,是设计选择:
- 避免用
int,统一用int64或float64接收不确定的数字字段 - 若必须强转,可先解到
json.Number,再手动调.Int64()或.Float64(),捕获ErrSyntax - 第三方库如
github.com/mitchellh/mapstructure在处理 map-style 解析时对数字更宽容,但标准库不会妥协
嵌套对象缺失时 panic 而非跳过
当 JSON 中某个嵌套对象字段缺失(如 "address": null),而你的 struct 定义是 Address AddressInfo(非指针),json.Unmarshal 会尝试对零值 AddressInfo{} 调用其字段的反序列化——如果其中某个字段又是非指针值类型(如 ZipCode int),而 JSON 里 address 是 null,就会 panic:json: cannot unmarshal null into Go struct field Address.ZipCode of type int。
根本原因在于:Go 不允许把 null 解到非指针、非接口的值类型字段。
- 关键对策:对可能为
null的嵌套对象,一律使用指针字段(*AddressInfo) - 或改用
map[string]interface{}先粗粒度解析,再按需提取和类型断言 - 不要依赖“字段不存在就跳过”——只要字段在 struct 中声明了,且 JSON 里对应 key 是
null,就一定会报错(除非是*T或interface{})
最常被忽略的一点:Go 的 JSON 解析器不做 schema 校验,也不提供“宽松模式”。它只做严格类型匹配和字段映射。所谓“解析成功”,不代表数据语义正确;所谓“没报错”,不代表所有字段都被赋了值。真正健壮的 JSON 处理,永远始于对 struct 定义的审慎,而非对 Unmarshal 的盲目信任。










