写点什么

jackson 解析泛型的正确写法

用户头像
4ye
关注
发布于: 2021 年 08 月 09 日

解决 1024 当天遗留的 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')
复制代码


错误代码如下:

  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 中的一个元素就报错上面那个错了🙃🙄 两种写法都会报这个错误。。


整个人都懵了,找了好久都不知道咋回事。。

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);
复制代码

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

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


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

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



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

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

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


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


结论

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>>>(){});,直接一步到位。


"( ̄y▽, ̄)╭ " 😄


最后

欢迎小伙伴们来一起探讨问题~


如果你觉得本篇文章还不错的话,那拜托再点点赞支持一下呀😝

让我们开始这一场意外的相遇吧!~

欢迎留言!谢谢支持!ヾ(≧▽≦*)o 冲冲冲!!

我是 4ye 咱们下期应该……很快再见!! 😆

发布于: 2021 年 08 月 09 日阅读数: 9
用户头像

4ye

关注

公众号:J a v a 4 y e 2021.07.19 加入

还未添加个人简介

评论

发布
暂无评论
jackson解析泛型的正确写法