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') 复制代码
网络异常,图片无法展示
|
错误代码如下:
- 第一种写法
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)); *//这里报错了* 复制代码
- 第二种写法
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
来存解析的数据🐖
网络异常,图片无法展示
|
错误分析之错误代码的第二种写法
objectMapper.readValue(body, Map.class);
这里也是,没办法指定泛型🐖,
所以jackson还是使用了这个LinkedHashMap
来存解析的数据
网络异常,图片无法展示
|
分析到这里有点悟出来了!怎么才能将泛型加上去啊!🐖
方案二:使用泛型的正确写法如下:
ResultDTO<List<User>> listResultDTO = objectMapper.readValue(body, new TypeReference<ResultDTO<List<User>>>(){}); 复制代码
debug看一下,终于正确了!!😁
网络异常,图片无法展示
|
结论
jaskson 解析使用泛型类的时候,有两种做法
- 局部解析🐖:
- 通过
readTree()
去获取对应的jsonnode节点:JsonNode jsonNode = objectMapper.readTree(body);
- 再获取到对应节点的数据
jsonNode.get("data");
- 最后通过
readValue()
:objectMapper.readValue(data.toString(), new TypeReference<List<User>>(){});
解析得到对应的数据
- 直接解析🐖:
objectMapper.readValue(body, new TypeReference<ResultDTO<List<User>>>(){});
,直接一步到位。