如何使用 Jackson 动态为泛型包装类生成带类型名称的 JSON 结构
发布时间 - 2026-01-27 00:00:00 点击率:次本文介绍如何通过 jackson 的 `@jsontypeinfo` 与 `@jsontypename` 注解,结合泛型 wrapper 类,实现将不同子类型(如 payloadfoo、payloadbar)序列化为以类型名(如 `"foo"`、`"bar"`)为字段名的顶层 json 对象。
Jackson 原生不支持直接将泛型类型参数(如 Wr

关键实现步骤如下:
-
为 Wrapper 类添加多态元数据
使用 @JsonTypeInfo 启用类型识别,并设置 include = JsonTypeInfo.As.WRAPPER_OBJECT —— 这是实现 "foo": { ... } 结构的核心。同时配合 @JsonSubTypes 显式注册所有可能的子类型及其对应名称:@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, // ✅ 关键:生成外层命名包装对象 property = "" // 空字符串表示不额外添加类型字段,仅用键名体现类型 ) @JsonSubTypes({ @JsonSubTypes.Type(value = PayloadFoo.class, name = "foo"), @JsonSubTypes.Type(value = PayloadBar.class, name = "bar") }) @Data @NoArgsConstructor @AllArgsConstructor public static class Wrapper{ private SoaHeader soaHeader; private T payload; } -
为具体载荷类标注 @JsonTypeName
PayloadFoo 和 PayloadBar 需分别标注 @JsonTypeName("foo") 和 @JsonTypeName("bar"),确保 Jackson 能正确关联类型名与实现类:@JsonTypeName("foo") @Data public static class PayloadFoo { private String foo; } @JsonTypeName("bar") @Data public static class PayloadBar { private String bar; } -
注意泛型擦除限制与最佳实践
- Jackson 在运行时无法获取泛型 T 的真实类型(类型擦除),因此 Wrapper
必须作为多态基类参与序列化,不能仅靠泛型推断;必须显式注册所有子类型。 - @JsonTypeInfo.As.WRAPPER_OBJECT 要求被序列化的对象必须是 @JsonSubTypes 中声明的具体子类实例(如 new Wrapper
(...)),且需确保 payload 字段值非 null,否则可能触发空 Bean 异常(建议配置 configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false))。 - 若需更高灵活性(如动态注册类型),可考虑自定义 Serializer 或使用 ObjectWriter.withType() 显式指定类型,但会牺牲简洁性。
- Jackson 在运行时无法获取泛型 T 的真实类型(类型擦除),因此 Wrapper
最终,调用 ObjectMapper 序列化时即可获得预期结构:
WrapperfooWrapper = new Wrapper<>(new SoaHeader(), new PayloadFoo("test")); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(fooWrapper); // 输出: // { // "foo": { // "soaHeader": {}, // "payload": { // "foo": "test" // } // } // }
✅ 总结:该方案无需反射或手动构造 Map,完全基于 Jackson 标准注解,语义清晰、可维护性强,适用于 SOA 场景中统一响应包装器(如含 header + typed payload)的标准化 JSON 输出。
# js
# json
# app
# ai
# NULL
# 多态
# 子类
# include
# 泛型
# map
# 对象
# 序列化
# 这是
# 擦除
# 中统
# 适用于
# 更高
# 自定义
# 不支持
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
新三国志曹操传主线渭水交兵攻略
Python并发异常传播_错误处理解析【教程】
Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】
如何快速搭建高效香港服务器网站?
如何在万网开始建站?分步指南解析
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
香港服务器部署网站为何提示未备案?
如何用西部建站助手快速创建专业网站?
图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?
如何在服务器上配置二级域名建站?
详解Android——蓝牙技术 带你实现终端间数据传输
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
Laravel如何实现用户密码重置功能?(完整流程代码)
微信小程序 scroll-view组件实现列表页实例代码
Laravel如何从数据库删除数据_Laravel destroy和delete方法区别
深圳网站制作平台,深圳市做网站好的公司有哪些?
如何彻底卸载建站之星软件?
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
Laravel如何为API生成Swagger或OpenAPI文档
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
Laravel怎么使用artisan命令缓存配置和视图
如何在VPS电脑上快速搭建网站?
JavaScript数据类型有哪些_如何准确判断一个变量的类型
php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】
html5的keygen标签为什么废弃_替代方案说明【解答】
微信h5制作网站有哪些,免费微信H5页面制作工具?
Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】
,网页ppt怎么弄成自己的ppt?
Swift中swift中的switch 语句
潮流网站制作头像软件下载,适合母子的网名有哪些?
如何用狗爹虚拟主机快速搭建网站?
Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲
如何在香港服务器上快速搭建免备案网站?
Laravel如何优化应用性能?(缓存和优化命令)
在Oracle关闭情况下如何修改spfile的参数
桂林网站制作公司有哪些,桂林马拉松怎么报名?
如何快速完成中国万网建站详细流程?
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
活动邀请函制作网站有哪些,活动邀请函文案?
网站页面设计需要考虑到这些问题
JS经典正则表达式笔试题汇总
Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】
详解jQuery中基本的动画方法
佛山企业网站制作公司有哪些,沟通100网上服务官网?
个人网站制作流程图片大全,个人网站如何注销?
如何注册花生壳免费域名并搭建个人网站?

