百日筑基第五十天-TypeReference-FastJson详解

百日筑基第五十天-TypeReference-FastJson详解

TypeReference是一个描述复杂泛型的工具类。很多类库都有,我们使用alibaba.fastjson来举例。

在反序列化场景中获取泛型参数。
TypeReference支持泛型参数,方便一些框架实现通用的反序列化类,对复杂的类型可以很方便的反序列化。
使用Gson、Jackson或Fastjson反序列化泛型时,需要传递泛型的真实类型,所以一般都通过集成TypeReference来实现。

简单示例

@Slf4j(topic = "juc")
public class TypeRefrenceStudy {
    public static void main(String[] args) {
        List<Integer> list = Lists.newArrayList(1, 3, 4, 8, 9);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("list", list);
        log.info(jsonObject.toString());

		// 使用匿名类创建TypeReference的子类对象
        List<Integer> list2 = jsonObject.getObject("list", new TypeReference<List<Integer>>() {});
        log.info("list2 {}", list2);
    }
}

执行结果:

16:07:37.122 [main] juc - {"list":[1,3,4,8,9]}
16:07:37.141 [main] juc - list2 [1, 3, 4, 8, 9]
  • 使用TypeReference可以明确指定反序列化的类型,能够比较方便的获取反序列化的数据。

复杂示例

例子:

Response response = JSONObject.parseObject(result, new TypeReference<Response>(TaskCodeRespData.class) {});

等价于:

Response response = JSONObject.parseObject(result, new TypeReference<Response>( ) {})

如果要用泛型变量 ,有参数的写法就相当必要了。

单参数例子
public class Response {
	public T data;
}
public static Response parseToMap(String json, Class type) {
    return JSON.parseObject(json, new TypeReference<Response>(type) {});
}
双参数例子
public static <K, V> Map<K, V> parseToMap(String json, Class keyType, Class valueType) {
	return JSON.parseObject(json, new TypeReference<Map<K, V>>(keyType, valueType) {});
}
// 可以这样使用
String json ={1:{name:“ddd”},2:{name:“zzz”}};
Map<Integer, Model> map = parseToMap(json, Integer.class, Model.class);
assertEquals(“ddd”, map.get(1).name);
assertEquals(“zzz”, map.get(2).name);

一个重要实战样例

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>>(){});
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值