根本原因是结构体字段未导出(首字母小写),encoding/json包仅能序列化首字母大写的导出字段,小写字段如name、things会被静默忽略,导致json.marshal返回{}或null。

json.Marshal 为什么输出空对象或 null?
根本原因通常是结构体字段未导出(首字母小写),json.Marshal 只能访问导出字段。比如 type User struct { name string },name 不会被序列化,结果是 {} 或嵌套时变成 null。
- 确保字段名首字母大写:改
name string为Name string - 若需保留小写 key 名,用 struct tag:
Name string `json:"name"` - 零值字段(如空字符串、0、nil 切片)默认仍会输出,想跳过就加
omitempty:Age int `json:"age,omitempty"` - 注意指针字段:若
*string为nil,带上omitempty才不输出;否则输出null
json.Marshal 和 json.MarshalIndent 的实际差异
json.Marshal 输出紧凑 JSON(无换行/缩进),json.MarshalIndent 用于调试或配置生成,但别在日志或网络传输中默认用它——多出来的空格和换行会增大体积、影响解析性能。
- 签名区别:
json.Marshal(v interface{})vsjson.MarshalIndent(v interface{}, prefix, indent string) -
prefix是每行开头的字符串(常设为空),indent是缩进符(如" "或"\t") - 两者底层共享编码逻辑,错误行为一致(比如遇到
func、chan会返回json.UnsupportedTypeError)
自定义类型怎么让 json.Marshal 正确工作?
如果结构体嵌套了自定义类型(如 type Email string),默认会按底层类型处理;但若该类型实现了 json.Marshaler 接口,就会优先调用它的 MarshalJSON() 方法。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 必须返回
[]byte和error,且字节必须是合法 JSON(比如带双引号的字符串) - 常见错误:直接返回
[]byte(e)而没包引号 → 解析失败;正确写法是return json.Marshal(string(e)) - 注意循环引用:在
MarshalJSON里又调用了json.Marshal(this)会导致栈溢出 - 如果只是想复用原生逻辑+加一层包装,可先
data, _ := json.Marshal(*(*struct{...}*)(unsafe.Pointer(&e))),但更推荐组合匿名结构体
“交换” Marshal 和 Unmarshal 时最易忽略的坑
所谓“交换”,通常指把 A 类型 Marshal 出来的字节,用 B 类型 Unmarshal —— 这只有在字段名、类型、tag 完全兼容时才安全。Go 不做运行时类型校验,错配后静默丢失数据或赋零值。
- 字段名大小写必须一致:A 有
Name,B 必须也有导出的Name,不能是name - 基础类型要可转换:JSON 数字 → Go
int没问题,但 →time.Time就会失败(除非用自定义UnmarshalJSON) - 切片和 map 的键类型必须匹配:JSON array → Go
[]stringOK,→map[string]string就 panic - 嵌套结构体 tag 不一致(比如一个用
json:"user_id",另一个用json:"uid")会导致字段无法绑定
真正需要“交换”的场景(如微服务间协议适配),建议显式定义中间 DTO 类型,而不是依赖结构体字段自动对齐。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










