怎么利用 Jackson 的 Polymorphic Deserialization 实现对包含不同子类型的 JSON 列表的自动解构

秋晨大大_1701

秋晨大大_1701

2026-05-03

373人浏览

原创

Jackson 能自动将带 type 字段的 JSON 数组反序列化为子类对象列表,前提是正确配置 @JsonTypeInfo 与 @JsonSubTypes、注册子类、使用 TypeReference 指定泛型,并确保 JSON 中类型标识字段名和值严格匹配声明。

怎么利用 jackson 的 polymorphic deserialization 实现对包含不同子类型的 json 列表的自动解构

直接说结论:用 @JsonTypeInfo + @JsonSubTypes 注解在基类上声明多态规则,并确保 JSON 中有明确的类型标识字段(如 "type" 或 "messageType"),Jackson 就能自动把 JSON 数组反序列化为具体子类对象的 List,无需手动判断或 if-else。

JSON 必须带 type 字段,且位置要对

Jackson 的多态反序列化不是“猜类型”,而是严格匹配你声明的标识字段。如果 JSON 长这样:

[{"make":"Ford","model":"Focus"},{"make":"Toyota","model":"Tacoma","maxLoad":1050}]

——它没有 type 字段,Jackson 根本不知道第二个对象该映射成 Truck 还是 Car,会直接报 UnrecognizedPropertyException。

正确做法是让上游加字段,或用预处理补全。常见合法结构包括:

  • {"type":"car","make":"Ford","model":"Focus"}(type 在对象内部)
  • {"messageType":6,"payload":{"url":"xxx"}}(需配合 JsonTypeInfo.As.EXTERNAL_PROPERTY)
  • {"@class":"com.example.Truck","make":"Toyota","maxLoad":1050}(CLASS 策略,慎用)

@JsonTypeInfo 的 use 和 property 参数必须匹配 JSON

这两个参数决定了 Jackson 去哪找、怎么读类型信息。错配 = 反序列化失败。

最常用组合是:

  • use = JsonTypeInfo.Id.NAME:靠逻辑名(如 "car"、"truck")查注册表
  • property = "type":要求每个 JSON 对象里都有 "type": "xxx" 字段

如果 JSON 用的是 "msgType",你就得写 property = "msgType";如果类型值是数字 7,就得用 Id.CUSTOM 配合自定义解析器,不能硬套 NAME。

别漏掉 visible = true(尤其用 NAME 时),否则序列化出的 JSON 不带 type 字段,下游无法反解。

子类必须显式注册,不能只靠继承关系

Jackson 不会自动扫描子类。哪怕 Truck extends Car,不注册,它就永远当 Car 解。

JSON Toolkit
JSON Toolkit

JSON文件多功能工具。支持格式化、验证、压缩、键排序及点记法路径查询。零依赖。

下载

注册方式有两种:

  • 注解方式(推荐):@JsonSubTypes({@Type(value = Truck.class, name = "truck")}) 写在基类上
  • 运行时注册:mapper.registerSubtypes(Truck.class),适合动态加载场景

注意 name 值必须和 JSON 中的字符串完全一致(大小写敏感),且不能重复。多个子类共用一个 name 会导致随机覆盖。

数组反序列化要指定泛型类型,不能只写 List.class

这是最容易翻车的操作:

mapper.readValue(json, List.class); // ❌ 全变成 LinkedHashMap

必须用 TypeReference 保留泛型信息:

mapper.readValue(json, new TypeReference<list>>() {}); // ✅</list>

否则 Jackson 默认按 Map 处理每个对象,你拿到的是 List,字段全丢,还看不出错在哪。

如果基类是抽象的(比如 abstract class Message),也要确保目标类型写的是基类,不是具体子类——Jackson 会根据 type 字段自己选。

真正麻烦的不是配置,而是协调:JSON 结构、注解声明、子类注册、反序列化调用这四者必须严丝合缝。少对一环,就退化成 Map 填充,或者直接抛异常。尤其当类型字段在兄弟节点(如 messageType 和 payload 并列)时,EXTERNAL_PROPERTY 的用法很容易被忽略,导致 payload 死活不进子类。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

js json

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

12517

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

9622

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

8192

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1324

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

1048

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1576

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

3289

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20511

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1435

8

热门下载

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

精品课程

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

共101课时 | 21.3万人学习

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

共39课时 | 4.9万人学习