当前位置: 首页 > 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.jsqmd.com/news/998787/

相关文章:

  • 公共交通票价模型解析:从计费里程到换乘优惠的逆向工程
  • 视觉多向量检索技术:突破传统文档检索的局限
  • 3分钟快速上手QKeyMapper:Windows平台终极按键映射解决方案
  • (Arcgis)matlab编程批量处理hdf5格式转换为tif格式
  • 德宏傣族景颇族自治州2026年黄金回收白银回收铂金回收权威门店 TOP5+正规可靠机构电话与地址汇总 - 马刺总冠军
  • 基于昇腾 CANN 与昇腾NPU asc-devkit 仓库,详细讲解 Ascend C 算子编程语言的环境准备、内核实现、编译运行全流程,配合真实代码示例与效率对比,帮助开发者快速掌握昇腾 NPU
  • 终极指南:如何一键备份你的QQ空间青春回忆
  • WechatDecrypt:如何用开源工具破解微信数据库的AES-256-CBC加密?
  • Manim数学动画引擎:5分钟学会制作专业级数学可视化视频
  • (Arcgis)matlab编程批量处理hdf4格式转换为tif格式
  • 2026昌都建筑材料检测权威机构排行 TOP 建材检测 + 见证取样 + 主体结构检测 附电话地址 - 中检检测集团
  • AI率太高怎么办?亲测这3款热门降AI工具,免费指令真的能避坑
  • 德宏市手表回收包包回收哪家店更好,2026甄选以下5家店铺排名前5 - 谊识预商务
  • Simple Transformers三行代码实现文本摘要
  • EVB9S12XEP100评估板:从硬件解析到外设驱动的嵌入式开发实战
  • 2026保定本地人认可的 5 家户外广告设施检测机构实地测评汇总+市民高频选择 - 中安检测集团
  • 办公被频繁弹窗打扰?教你关掉 Office 自动弹出的 AI 助手
  • DisplayMagician:游戏玩家的一键显示配置神器,3分钟实现多屏自动切换
  • 富士Micrex-F系列PLC编程软件PC Programmer安装包(含中英文双语支持)
  • MC3S12R系列汽车级MCU:ROM掩膜、CAN与高可靠嵌入式设计解析
  • 膜宇宙理论中的暴胀模型与各向异性抑制机制
  • 如何在5分钟内为Unity游戏选择最佳免费去马赛克插件?UniversalUnityDemosaics终极指南
  • Android Studio中文语言包终极指南:3步告别英文界面,提升开发效率30%
  • MC68HC916X1 QSPI与SCI通信模块深度解析与实战配置指南
  • 第十三章 集合【开发的重点】
  • LinkSwift:九大网盘直链下载助手的终极使用指南
  • 第十四章 异常
  • 革命性英雄联盟智能助手Seraphine:一站式战绩分析与BP优化解决方案
  • 2026百色企业高频选择的 5 家高分子检测第三方机构实地测评整理 - 鉴安检测
  • MPC5676R通信与调试模块深度解析:FlexCAN、FlexRay与Nexus实战指南