当前位置: 首页 > news >正文

go一个大坑 核心问题:同名同 JSON tag 字段的处理

核心问题:同名同 JSON tag 字段的处理

场景描述

外层泛型结构体:

go

type IchubResult[T any] struct { *basedto.IchubResult // 指针嵌入 Data T `json:"data"` // 外层 Data Total int `json:"total"` ... }

内层嵌入结构体basedto.IchubResult

go

type IchubResult struct { Code int `json:"code"` Msg string `json:"msg"` Data any `json:"data"` // 内层也有 Data! ... }

两者都设置了值

go

result := &IchubResult[string]{ IchubResult: &basedto.IchubResult{ Code: 0, Msg: "success", Data: "inner value", // 内层 Data }, Data: "outer value", // 外层 Data Total: 100, }

Go JSON 序列化的实际行为

关键规则:

嵌入类型外层 Data内层 DataJSON 结果
值类型嵌入basedto.IchubResult有值有值外层优先(内层被隐藏)
指针类型嵌入*basedto.IchubResult有值有值内层优先!(内层 Data 被序列化)

为什么内层优先?

这是 Goencoding/json处理指针嵌入的特殊行为:

  1. 指针嵌入的字段提升规则:当嵌入指针非 nil 时,其字段会被提升到外层
  2. 字段冲突处理:外层同名字段会"遮蔽"(shadow)内层字段
  3. 但是!JSON 序列化时,指针嵌入的字段会被单独遍历,可能导致重复 key

实际序列化流程:

go

// 遍历顺序(简化) 1. 遍历外层结构体的直接字段 → 找到 Data (外层) 2. 遍历嵌入指针的字段 → 找到 Data (内层) 3. 两个字段都被序列化,内层覆盖外层(取决于遍历顺序)

解决方案

方案一:使用值类型嵌入

go

type IchubResult[T any] struct { basedto.IchubResult // 值类型嵌入,外层优先 Data T `json:"data"` ... }

方案二:修改内层结构体的 JSON tagbasedto.IchubResultData字段改为其他名称,或移除。

方案三:手动控制序列化实现MarshalJSON方法:

go

func (r *IchubResult[T]) MarshalJSON() ([]byte, error) { type Alias IchubResult[T] return json.Marshal(&struct { *Alias Data T `json:"data"` // 显式指定使用外层 Data }{ Alias: (*Alias)(r), Data: r.Data, }) }

验证测试

go

package main import ( "encoding/json" "fmt" ) type Inner struct { Data any `json:"data"` } type Outer[T any] struct { *Inner Data T `json:"data"` } func main() { outer := &Outer[string]{ Inner: &Inner{Data: "inner"}, Data: "outer", } b, _ := json.Marshal(outer) fmt.Println(string(b)) // 输出: {"data":"inner"} // 内层优先! }

结论

当使用指针嵌入且内外层都有同名同 JSON tag 的字段时,内层字段的值会出现在最终的 JSON 输出中。

这是因为指针嵌入的字段提升机制与 JSON 序列化的遍历顺序共同作用的结果。建议使用值类型嵌入来确保外层字段优先。

http://www.rkmt.cn/news/1510558.html

相关文章:

  • 德宏市手表回收包包回收哪家店更好,2026甄选以下5家店铺排名前5 - 谊识预商务
  • Simple Transformers三行代码实现文本摘要
  • AI率太高怎么办?亲测这3款热门降AI工具,免费指令真的能避坑
  • 2026昌都建筑材料检测权威机构排行 TOP 建材检测 + 见证取样 + 主体结构检测 附电话地址 - 中检检测集团
  • EVB9S12XEP100评估板:从硬件解析到外设驱动的嵌入式开发实战
  • WechatDecrypt:如何用开源工具破解微信数据库的AES-256-CBC加密?
  • DisplayMagician:游戏玩家的一键显示配置神器,3分钟实现多屏自动切换
  • MC68HC916X1 QSPI与SCI通信模块深度解析与实战配置指南
  • 如何在5分钟内为Unity游戏选择最佳免费去马赛克插件?UniversalUnityDemosaics终极指南
  • 膜宇宙理论中的暴胀模型与各向异性抑制机制
  • 第十三章 集合【开发的重点】
  • 2026百色企业高频选择的 5 家高分子检测第三方机构实地测评整理 - 鉴安检测
  • 揭阳市2026年本地黄金回收铂金白银回收哪家强?TOP5 正规门店榜单 +联系方式 - 开始就结束
  • 晋城市2026年本地黄金回收铂金白银回收哪家强?TOP5 正规门店榜单 +联系方式 - 开始就结束
  • QKeyMapper:解放你的双手,重新定义Windows输入体验
  • 从法拉第笼到你的桌面:万兆屏蔽网线为何能跑满10Gbps?一次讲清原理与选购
  • 如何用免费开源甘特图工具GanttProject实现专业项目管理
  • ncmdumpGUI:让网易云音乐NCM格式文件重获自由的全能工具
  • [智能体-373]:具身智能体(离物理世界最近)、终端智能体(与人交互)、云端智能体(离物理世界最远)三者的对比
  • QKeyMapper终极指南:5分钟掌握Windows最强按键映射工具,让游戏手柄秒变键鼠!
  • MPC5561在ADAS开发中的核心架构与实战应用解析
  • IBN-Net预训练模型使用指南:快速迁移学习到你的自定义任务
  • 景德镇市2026年本地黄金回收铂金白银回收哪家强?TOP5 正规门店榜单 +联系方式 - 开始就结束
  • OpenCL C数据类型详解:从基础到实战的性能优化指南
  • LLM代理生态中的恶意工具攻击与防御实践
  • 从MCF5102看嵌入式CPU设计:可变长度RISC如何平衡性能与成本
  • PURE项目深度解析:两阶段实体关系抽取的简单高效实现
  • 直播间粉丝沉淀:海外社群分层与长效变现实操
  • 从‘无穷细分’到‘一键求解’:牛顿-莱布尼茨公式如何让MATLAB/ Wolfram Alpha秒算定积分?
  • 2026自贡黄金回收铂金回收银饰回收优质商户排名 TOP 线下实体门店实地走访资料汇总(更新时间:2026-06-12_11:10:26) - 信誉隆金银铂奢回收