结构体字段必须首字母大写才能被json.unmarshal读取,小写字段即使有json:"key"标签也会被静默忽略并保持零值;嵌套字段、容器层及动态key均需严格遵循导出规则与显式标签映射。

结构体字段必须首字母大写才能被 json.Unmarshal 读取
Go 的 encoding/json 包无法访问小写字母开头的字段,无论是否写了 json:"xxx" 标签。这是 Go 的导出规则决定的,不是 bug,但会导致字段静默为零值(空字符串、0、nil 切片),且不报错。
常见错误现象:解析后结构体看起来“成功”,但嵌套字段全是零值,比如 Gateways 切片长度为 0、Name 是空字符串。
- ✅ 正确写法:
Name string `json:"name"`(首字母大写 + 显式 tag) - ❌ 错误写法:
name string `json:"name"`(即使有 tag,也不会被赋值) - ⚠️ 注意:嵌套结构体里的字段也必须全部首字母大写,否则内层照样为空
嵌套对象必须用命名结构体字段,不能靠匿名嵌入“省事”
json.Unmarshal 不会自动提升或展开嵌套层级。把 Nest Nest `json:"nest"` 写成 Nest `json:"nest"`(缺类型)或直接嵌入 Nest(无字段名),Go 会当成结构体嵌入(embedding),期望 JSON 是 {"id":"123"},而不是 {"nest":{"id":"123"}} —— 结果就是字段解不出来。
使用场景:JSON 中存在明确容器层(如 "data"、"payload"、"response"),业务上它只是包裹,没有独立语义。
- ✅ 推荐:保留该字段,定义为
Data DataResp `json:"data"`,避免过度展开 - ❌ 避免:强行定义
Response.Data.List[0].Item.ID对应的四级嵌套 struct - ? 拆分类型比“一层到底”更稳:深层嵌套时,用中间类型(如
type DataResp struct { List []Item })降低维护成本
数组里混着不同结构?用 json.RawMessage 延迟解析
当 JSON 数组元素类型不一致(如 [{"type":"user","name":"A"},{"type":"admin","level":9}]),直接解到统一 struct 会失败,报错类似:json: cannot unmarshal object into Go struct field。
根本原因:json.RawMessage 是 []byte 别名,不触发解析,零拷贝保留原始字节;但它只能作为 struct 字段类型,不能用于局部变量直接 json.Unmarshal。
- ✅ 正确做法:声明字段为
Items []json.RawMessage `json:"items"` - ✅ 解析时遍历每个
json.RawMessage,先取type字段判断,再二次解码到对应 struct - ⚠️ 常见坑:误以为
json.RawMessage是“可重读流”,其实它本身无状态,可以多次用,但别反复 Unmarshal 同一段数据
传参别把包名当变量:json.Unmarshal 第二个参数必须是真实数据
最常踩的坑之一:在函数里写 json.Unmarshal(json, &parsed),这里的 json 是 encoding/json 包名,不是数据变量——轻则编译报错,重则运行时 panic。
正确流程必须显式接收真实 JSON 数据(通常是 []byte),并传给 json.Unmarshal。
- ✅ 正确签名:
func ParseResponse(data []byte) error - ✅ 调用:
err := json.Unmarshal(data, &parsed) - ⚠️ 注意:不要在函数体内重命名
encoding/json包为json,尤其当变量名也叫json时,极易混淆
json.RawMessage 生命周期的理解。稍一松懈,就容易在“看似成功”的静默失败里浪费半天时间。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











