Jackson是一个比较流行的Json序列化和反序列化框架。本文以Jackson为例介绍TypeReference实现涉及泛型的反序列化,及TyperReference的实现原理。对于获取泛型类型信息的场景,TypeReference是一个可以参考的通用解决方案。
Jackson ObjectMapper的readValue可以将Json字符串反序列化为Java对象。
例:如将下列Json串反序列化为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;
}
 
1)理想的实现方式:
理想的实现方式是告诉ObjectMapper的readValue方法,我要的是List<UserResource>,帮我反序列化成这个类型。
List<UserResource> list = new ObjectMapper().readValue(userResourcesStr, List<UserResource>.class);
 
现实的编译器告诉你这不行,Cannot select from parameterized type. 也很好理解,Java编译器认为List是Class,而List则不是。
2)换一种实现方式
既然不能用List<Resource>.class,那如果我告诉ObjectMapper的readValue方法,我要的是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类型。如下图所示:

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

List<UserResource> list = new ObjectMapper().readValue(userResourcesStr, new TypeReference<List<UserResource>>(){});
 

 4)TypeReference实现原理
上例中new TypeReference<List<UserResource>>(){}子类的实例,TypeReference源码部分比较简单,主要逻辑是,通过getClass().getGenericSuperclass();获取父类中的参数化类型(ParameterizedType)。
这部分不清楚可以看:Java 中的Type类型及其实现【学习记录】
TypeReference主要源码:
protected TypeReference()
{
    Type superClass = getClass().getGenericSuperclass();
    _type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
 
getGenericSuperclass返回一个Type类型的对象,代表实体(class,interface,primitive type or void)的直接父类,如果父类是参数化类型,则返回的Type对象可准确反应源码中使用的实际type参数。
Class的genericInfo:

 5)总结:
- Jackson ObjectMapper 提供了TypeReference支持对泛型对象的反序列化;
 - 对于获取泛型类型信息的场景,TypeReference是一个可以参考的通用解决方案。
 













![[Java 进阶面试题] HashTable, HashMap, ConcurrentHashMap 之间的区别](https://img-blog.csdnimg.cn/53be0c2809ac4af4bb51d70b293a06d0.png)





