json.unmarshal不返回解析结果,只返回error;nil表示成功,数据已写入传入的指针变量,常见失败原因包括传值非地址、字段未导出(小写)、缺失json tag或类型不匹配。

json.Unmarshal 不返回数据,只返回 error;解析结果写进你传的指针变量里——这是最常卡住人的第一关。
为什么 json.Unmarshal 返回 nil 却没拿到值
因为它的设计就是“写入式”而非“返回式”:只负责把 JSON 字节填进你给的地址,成功就返回 nil,失败才返回具体错误。你看到 err == nil,说明已经写进去了,但可能根本没检查目标变量。
- 传了
p而不是&p→ 编译通过,但结构体字段全是零值(Go 值传递) - 结构体字段是小写开头(如
name string)→ 完全忽略,不报错也不赋值 - 忘了加
json:"name"标签,且 JSON key 是下划线风格(如"user_id")→ 字段匹配不上,保持原值 - 调试时加一句
fmt.Printf("→ %+v", p),比只盯err有用十倍
结构体字段必须大写 + 正确用 json: 标签
Go 的 encoding/json 包只处理导出字段(首字母大写),且默认按字段名严格匹配 JSON key。外部 API 几乎不用驼峰,所以光大写不够,必须靠标签对齐。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
-
User_id int `json:"user_id"`→ JSON 中是"user_id": 123才能写入 -
CreatedAt time.Time `json:"created_at"`→ 字段语义清晰,标签负责桥接 -
Options *[]string `json:"options,omitempty"`→omitempty只影响序列化,反序列化时缺失字段不修改原值 - 嵌套结构体同理:内层字段也得大写 + tag,漏一层,整层为零值
遇到 null、缺失字段或类型不匹配怎么处理
json.Unmarshal 的容错策略是“尽力而为”,但也因此容易掩盖问题:
- JSON 是
null,目标字段是*string→ 赋值为nil(合理) - JSON 是
null,目标字段是string→ 不修改原值(若未初始化就是空字符串) - JSON 字段缺失(如没有
"email")→ 对应字段保持原值,不会清空 - JSON 字符串塞进
int字段 → 直接返回json.UnmarshalTypeError,不是跳过 - 想强制校验字段存在?得自己加逻辑,比如
if p.Email == "" { return errors.New("email required") }
别反复 Unmarshal 同一段 []byte
每次调用都重新做词法分析和语法树构建,开销不小。尤其在 API 网关或高频解析场景下,重复解析同一段原始 JSON 很浪费。
- 先用
json.RawMessage接住不确定结构的子字段,延迟解析 - 一次性解析成
map[string]interface{},再按需取值并手动转类型(仅限简单、低频场景) -
json.RawMessage保存的是原始字节引用,如果原始[]byte被复用或释放,它会失效 - 读文件时,用
os.ReadFile("config.json")拿到字节流再传给Unmarshal;别传路径字符串,会 panic
最容易被忽略的点:嵌套结构体里任意一层字段没导出或漏了 json: 标签,整层就静默丢失;null 对普通字段(非指针)不生效,它只是跳过——你以为是“设为空”,其实只是“没动它”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










