问题描述:
对于一个多层嵌套泛型(深度泛型)的对象进行序列化是容易的,但是反序列化却往往不是很顺利。
//调用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<AlUsers> usersList = Lists.newArrayList(alUsers1, alUsers2);
//设计的多泛型嵌套map
Map<String, List<AlUsers>> map = Maps.newHashMap();
map.put("L", usersList);
//序列化
String json = mapper.writeValueAsString(map)
我们设计了一个多层泛型嵌套的对象map,对其进行序列化,是没有问题的
//打印
{"L":[{"username":"WOW"},{"username":"SC2"}]}
我们现在使用反序列化处理
Map<String, List<AlUsers>> map1 = mapper.readValue(json, Map.class);
List<AlUsers> 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<String, String> 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<String, List<AlUsers>> map1 = mapper.readValue(json, Map.class);
List<AlUsers> 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<String, List<AlUsers>> map1 = mapper.readValue(json, new TypeReference<Map<String, List<AlUsers>>>(){});
List<AlUsers> users = map1.get("L");
for (AlUsers user : users) {
System.out.println(mapper.writeValueAsString(user));
}
//打印
{"username":"WOW"}
{"username":"SC2"}
版权声明:本文为qq_45337431原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。