0

0

如何在Golang中通过反射实现对象的JSON映射_Golang反射与JSON映射的结合

P粉602998670

P粉602998670

发布时间:2026-02-24 11:23:02

|

661人浏览过

|

来源于php中文网

原创

go 的 json 序列化默认通过 struct tag 控制,无需手动反射;仅在需动态字段名、批量检查或构建通用工具时才需主动用反射解析 tag。

如何在golang中通过反射实现对象的json映射_golang反射与json映射的结合

Go 的 json 包本身不依赖反射做序列化,但反射是实现自定义映射逻辑(比如字段名动态计算、忽略空值策略切换、嵌套结构扁平化)的底层支撑。直接用 json.Marshal 和 struct tag 就能解决 90% 的需求;只有当你需要绕过默认行为、或构建通用工具(如 ORM 字段映射器、配置注入器)时,才真正需要手动介入反射。

struct tag 是 JSON 映射的默认控制入口

Go 的 JSON 序列化优先读取 struct 字段上的 json tag,而非字段名本身。反射只是读取它的手段,不是必须绕进去写逻辑的起点。

  • json:"name":指定序列化后的键名
  • json:"name,omitempty":该字段为空值(零值)时不输出
  • json:"-":完全忽略该字段
  • 未加 tag 且字段首字母小写 → 不可导出 → json.Marshal 自动跳过

例如:

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name,omitempty"`
    pwd  string `json:"-"` // 小写 + "-" → 完全屏蔽
}
这种写法无需反射,json.Marshal 内部已通过反射读取 tag 并处理。

用反射读取 struct tag 实现运行时字段控制

当字段名需动态生成(如根据环境加前缀)、或需批量检查哪些字段参与序列化时,才需要主动用反射提取 tag。核心是 reflect.StructTag.Get

  • 必须先用 reflect.TypeOf(v).Elem() 获取 struct 类型(若传入指针)
  • 遍历 NumField,对每个 Field 调用 Tag.Get("json")
  • Tag.Get("json") 返回完整 tag 字符串(如 "name,omitempty"),需自行解析逗号分隔部分
  • 注意:Tag.Get 对不存在的 key 返回空字符串,不是 panic

示例:提取所有非忽略字段名

func getJSONKeys(v interface{}) []string {
    t := reflect.TypeOf(v)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    if t.Kind() != reflect.Struct {
        return nil
    }
    var keys []string
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag := field.Tag.Get("json")
        if jsonTag == "-" || jsonTag == "" {
            continue
        }
        key := strings.Split(jsonTag, ",")[0]
        if key != "" {
            keys = append(keys, key)
        }
    }
    return keys
}

反射修改字段值后再 JSON 序列化需注意可导出性

想用反射给 struct 字段赋值再序列化?那字段必须是可导出的(首字母大写),否则 reflect.Value.Set 会 panic:"reflect: reflect.Value.Set using unaddressable value"。

Hotpot.ai
Hotpot.ai

AI工具箱(图像、游戏和写作系列工具)

下载

立即学习go语言免费学习笔记(深入)”;

  • 传入的 struct 实例必须是指针(&v),否则 reflect.ValueOf(v) 得到的是不可寻址副本
  • 即使字段有 json tag,若字段名小写 → 不可导出 → 反射无法 Set,json.Marshal 也无法读取
  • 临时构造 map[string]interface{} 再序列化更安全,适合动态场景

错误示范:

type User struct {
    id int `json:"id"` // 小写 → 不可导出 → 反射 Set 失败
}
u := User{}
rv := reflect.ValueOf(&u).Elem()
rv.FieldByName("id").SetInt(123) // panic!

性能与调试成本:别为简单映射引入反射

反射调用比直接字段访问慢 10–100 倍,且破坏静态类型检查。常见误用是:本可用 map[string]interface{} 或预定义 struct 完成的映射,硬写一堆 reflect.Value.FieldByName

  • 如果只是把 HTTP 请求 body 解成 struct → 用 json.Unmarshal + tag
  • 如果要支持多种命名风格(snake_case / camelCase)自动转换 → 写一个通用的 UnmarshalJSON 方法,内部用反射一次解析 tag,缓存映射表
  • 如果字段逻辑复杂(如时间戳转 RFC3339、密码字段自动哈希)→ 为 struct 实现 json.Unmarshaler 接口,而不是在外部用反射塞值

最易被忽略的一点:json 包对嵌套 struct、interface{}、nil slice 的处理规则,和反射获取的字段顺序、零值判断并不总是一致——调试时要同时看 JSON 输出和 fmt.Printf("%+v", v) 的反射展开结果。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

207

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

242

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

349

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

212

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

405

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

365

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

200

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

1091

2025.06.17

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1228

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 9.6万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号