博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jackson多层泛型深度嵌套导致的反序列化问题
阅读量:3963 次
发布时间:2019-05-24

本文共 2827 字,大约阅读时间需要 9 分钟。

问题描述:

对于一个多层嵌套泛型(深度泛型)的对象进行序列化是容易的,但是反序列化却往往不是很顺利。

//调用jackson对象ObjectMapper mapper = new ObjectMapper();mapper.setSerializationInclusion(Include.NON_NULL); //封装用户对象AlUsers alUsers1 = new AlUsers();alUsers1.setUsername("WOW");AlUsers alUsers2 = new AlUsers();alUsers2.setUsername("SC2");List
usersList = Lists.newArrayList(alUsers1, alUsers2);//设计的多泛型嵌套mapMap
> map = Maps.newHashMap();map.put("L", usersList);//序列化String json = mapper.writeValueAsString(map)

我们设计了一个多层泛型嵌套的对象map,对其进行序列化,是没有问题的

//打印{
"L":[{
"username":"WOW"},{
"username":"SC2"}]}

我们现在使用反序列化处理

Map
> map1 = mapper.readValue(json, Map.class);List
users = map1.get("L");for (AlUsers user : users) {
System.out.println(mapper.writeValueAsString(user));}

结果抛出了异常

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.flight.carryprice.entity.AlUsers

Jackson是不支持多泛型深度嵌套反序列化的,强转后的结果就是默认将AlUsers对象变成了LinkedHashMap,所以在循环的时候强转AlUsers对象就会报错

即使我在每一层都序列化一次,最后还是报错

String listStr = mapper.writeValueAsString(usersList); //内层序列化Map
map = Maps.newHashMap();map.put("L", listStr);String json = mapper.writeValueAsString(map); //外层序列化//异常java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.flight.carryprice.entity.AlUsers

解决办法:

这里提供两种解决思路

1、既然问题出在循环过程中对象的强转,那么我们可以使用普通的for循环,使用get(index)方法获取对象的时候先转为json,再反序列化为AlUsers,中间倒腾一手

Map
> map1 = mapper.readValue(json, Map.class);List
users = map1.get("L");for (int i = 0; i < users.size(); i++) {
//序列化再反序列化 AlUsers alUsers = mapper.readValue(mapper.writeValueAsString(users.get(i)), AlUsers.class); System.out.println(mapper.writeValueAsString(alUsers));}//打印{
"username":"WOW"}{
"username":"SC2"}

2、我们使用TypeReference对象

//源码 protected TypeReference() {
Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class
) {
// sanity check, should never happen throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information"); } /* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect * it is possible to make it fail? * But let's deal with specific * case when we know an actual use case, and thereby suitable * workarounds for valid case(s) and/or error to throw * on invalid one(s). */ _type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; }

TypeReference对象就是通过java反省机制,获取所指定的泛型的类型,在反序列中根据指定的泛型类型进行反序列化

//通过TypeReference指定反序列化的类型Map
> map1 = mapper.readValue(json, new TypeReference
>>(){
});List
users = map1.get("L");for (AlUsers user : users) {
System.out.println(mapper.writeValueAsString(user));}//打印{
"username":"WOW"}{
"username":"SC2"}

转载地址:http://ftgzi.baihongyu.com/

你可能感兴趣的文章
类图(Class diagram)—UML图(二)
查看>>
活动图(Activity Diagram)—UML图(四)
查看>>
C#方法重载(overload)方法重写(override)隐藏(new)
查看>>
CSS+DIV练手-公司
查看>>
CSS+DIV练手—鲜花展
查看>>
深入浅出JavaScript(1)—ECMAScript
查看>>
深入浅出JavaScript(2)—ECMAScript
查看>>
Asp.Net+Jquery.Ajax详解1-开篇
查看>>
我的软件工程之路(四)—半年总结
查看>>
Asp.Net+Jquery.Ajax详解5-$.getScript
查看>>
Asp.Net+Jquery.Ajax详解6-$.ajaxSetup
查看>>
什么是Dojo?与Jquery宏观对比,结果如何?
查看>>
Asp.Net+Jquery.Ajax详解8-核心$.ajax
查看>>
项目中一个用于导出word的方法
查看>>
测试Jsp 静态包含和动态包含
查看>>
简析几种常用的Web监听
查看>>
Web应用过滤器Fileter
查看>>
代理模式(Proxy)
查看>>
采用动态代理对事务进行封装
查看>>
Hibernate性能优化
查看>>