Java泛型 | Jackson TypeReference获取泛型类型信息

前言

Jackson是一个比较流行的Json序列化和反序列化框架。本文以Jackson为例介绍TypeReference实现涉及泛型的反序列化,及TypeReference的实现原理。对于获取泛型类型信息的场景,TypeReference是一个可以参考的通用解决方案。

实例

Jackson ObjectMapper的readValue可以将Json字符串反序列化为Java对象。如下例中将[{"id":null,"name":" ","age":500,"gender":false,"email":"email","employed":true,"salary":10}]反序列化为List<UserResource>类型。

Json字符串:

复制代码
[{
    "id": null,
    "name": " ",
    "age": 500,
    "gender": false,
    "email": "email",
    "employed": true,
    "salary": 10
}]

UserResource实体类:

复制代码
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserResource {
    private UUID id;
    private String name;
    private int age;
    private boolean gender;
    private String email;
    private boolean employed;
    private BigDecimal salary;
}

实现

理想的实现方式

理想的实现方式是告诉ObjectMapperreadValue方法,我要的是List<UserResource>,帮我反序列化成这个类型。

复制代码
List<UserResource> list = new ObjectMapper().readValue(userResourcesStr, List<UserResource>.class);

现实是编译器告诉你这不行,Cannot select from parameterized type. 也很好理解,Java编译器认为List是Class,而List则不是。

换一种方式实现

既然不能用List<UserResource>.class, 那如果我告诉ObjectMapperreadValue方法,我要的是List类型,但返回值类型是List<UserResource>, 会发生什么呢?

复制代码
List<UserResource> list = new ObjectMapper().readValue(userResourcesStr, List.class);

这时候倒没有编译错误, 但是会有警告:Unchecked assignment: 'java.util.List' to 'java.util.List<UserResource>', 显然ObjectMapper并不能反序列化为UserResource类型,而是LinkedHashMap类型。如下图所示:

TypeReference的实现方式

ObjectMapper提供了readValue(String content, TypeReference valueTypeRef)接口,第二个参数为new一个TypeReference的子类实例:new TypeReference<List<UserResource>>(){}。泛型抽象类TypeReference用于通过子类获取完整的泛型类型信息。

复制代码
public <T> T readValue(String content, TypeReference valueTypeRef)
List<UserResource> list = new ObjectMapper().readValue(userResourcesStr, new TypeReference<List<UserResource>>(){});

TypeReference 实现原理

上例中new TypeReference<List<UserResource>>(){}子类的实例,TypeReference源码部分比较简单,主要逻辑是,通过getClass().getGenericSuperclass()获取父类中的参数化类型(ParameterizedType):

TypeReference主要源码:

复制代码
protected TypeReference()
    {
        Type superClass = getClass().getGenericSuperclass();
        _type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

getGenericSuperclass返回一个Type类型的对象,代表实体(class, interface, primitive type or void)的直接父类,如果父类是参数化类型,则返回的Type对象可准确反映源代码中使用的实际type参数。

Class的genericInfo:

总结

  • Jackson ObjectMapper 提供了TypeReference支持对泛型对象的反序列化;
  • 对于获取泛型类型信息的场景,TypeReference是一个可以参考的通用解决方案
相关推荐
babytiger2 小时前
为 Windows 和 Ubuntu 中设定代理服务器的详细方法
linux·windows·ubuntu
大数据魔法师5 小时前
Neo4j(一) - Neo4j安装教程(Windows)
windows·neo4j
扛枪的书生6 小时前
AD 侦查-AS-REP 烘烤攻击
windows·渗透·kali·提权·域渗透
我不是程序猿儿7 小时前
【C#】用 DevExpress 创建带“下拉子表”的参数表格视图
linux·windows·c#
flex88887 小时前
一个专为 Windows 用户设计的配置文件集合提供类似 Unix 环境的美化和功能增强。
服务器·windows·unix
kyy_studydiary8 小时前
Java知识点-Stream流
windows
ganjiee00079 小时前
leetcode 每日一题 1931. 用三种不同颜色为网格涂色
windows·python·leetcode
0xCC说逆向10 小时前
Windows逆向工程提升之二进制分析工具:HEX查看与对比技术
汇编·windows·单片机·嵌入式硬件·安全·pe结构·pe文件
正经教主11 小时前
【基础】Windows开发设置入门3:在 Windows 11 上设置开发驱动器,提升性能速度
windows·开发环境·开发驱动器
Xam_d_LM11 小时前
【Linux】如何清除 Ubuntu 留下的 EFI 分区,Windows 磁盘管理器右键删除卷是灰色
linux·运维·windows·ubuntu·重装系统·磁盘管理器