今天看啥  ›  专栏  ›  4ye酱

jackson解析泛型的正确写法 | Java Debug 笔记

4ye酱  · 掘金  ·  · 2021-05-15 10:55
阅读 81

jackson解析泛型的正确写法 | Java Debug 笔记

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

jackson解析泛型的正确写法

本期 4ye 又带来了一个小 bug 啦,如下,小伙伴们是否见过这个异常呢?

in unnamed module of loader 'app'

bug描述

上次使用jackson进行数据转换的时候发生了下面这个错误。

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.example.demo.model.User (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.example.demo.model.User is in unnamed module of loader 'app')
复制代码

20201024190656

错误代码如下:

  1. 第一种写法
 ObjectMapper objectMapper = new ObjectMapper();

  ResultDTO<Object> resultDTO = objectMapper.readValue(body, ResultDTO.class);

  List<String> data = (List<String>)resultDTO.getData();

  List<User> list = objectMapper.convertValue(data, new TypeReference<List<User>>() { });

  System.out.println(data);  

  System.out.println(list);

  System.out.println(list.get(0)); *//这里报错了* 
复制代码
  1. 第二种写法
 ObjectMapper objectMapper = new ObjectMapper();

  Map<String, List<User>> map = objectMapper.readValue(body, Map.class);

  List<User> data = map.get("data");

  User user = data.get(0);
复制代码

代码上body是从服务器获取到的数据,格式是{"data": [{},{}]}

转换成resultDTO也是正常的,可以拿到对应的data, 转换成list也是正常的!

然后bug来了!😱 去获取list中的一个元素就报错上面那个错了🙃🙄 两种写法都会报这个错误。。

整个人都懵了,无奈开启了 debug 之路~

ResultDTO代码如下:

*/***

 *** *@author* *RYZEYANG*

 ** @date 2020/10/24 14:50*

 **/*

@Data

public class ResultDTO<T> {

  */***

   ** 描述*

   **/*

  private String msg;

  */***

   ** 状态码*

   **/*

  private String code;

  */***

   ** 数据*

   **/*

  private T data;



}
复制代码

解决办法

突然想到自己之前也做过json的解析呀,那会都很顺利地解决的🐖

想着不用一步到位,先拿到那个节点的数据,再去转换看看。结果真的成功了!

方案一

代码如下:

  ObjectMapper objectMapper = new ObjectMapper();

  JsonNode jsonNode = objectMapper.readTree(body);

  System.out.println(jsonNode);

  JsonNode data = jsonNode.get("data");



  System.out.println(data);

  JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, User.class);

  List<User> users = objectMapper.readValue(data.toString(), javaType);
复制代码

错误分析之错误代码的第一种写法

因为前面ojectMapper.readValue(body, ResultDTO.class);这里没法定义泛型T的类型。。所以jackson使用了这个LinkedHashMap来存解析的数据🐖

20201027082329

错误分析之错误代码的第二种写法

objectMapper.readValue(body, Map.class); 这里也是,没办法指定泛型🐖,所以jackson还是使用了这个LinkedHashMap来存解析的数据

20201027082937

分析到这里有点悟出来了!怎么才能将泛型加上去啊!🐖

方案二:使用泛型的正确写法如下:

 ResultDTO<List<User>> listResultDTO = objectMapper.readValue(body, new TypeReference<ResultDTO<List<User>>>(){});
复制代码

debug看一下,终于正确了!!😁

20201027221941

结论

jaskson 解析使用泛型类的时候,有两种做法

  1. 局部解析🐖:
  • 通过readTree()去获取对应的jsonnode节点: JsonNode jsonNode = objectMapper.readTree(body);

  • 再获取到对应节点的数据jsonNode.get("data");

  • 最后通过readValue():objectMapper.readValue(data.toString(), new TypeReference<List<User>>(){}); 解析得到对应的数据

  1. 直接解析🐖:
  • objectMapper.readValue(body, new TypeReference<ResultDTO<List<User>>>(){});,直接一步到位。

我是 4ye 我们下期再见啦 ヾ( ̄▽ ̄)ByeBye




原文地址:访问原文地址
快照地址: 访问文章快照