jackson反序列化复杂泛型对象
最近在使⽤Redis 缓存数据的时候使⽤的spring 的aop⾃动从缓存中去区json数据。发现⽅法的返回值带有泛型时,直接简单的调⽤使⽤下⾯的⽅法⽆法拿到正确的结果。
Method method = ((MethodSignature) Signature()).getMethod();
Object[] args = Args();
//根据⽅法注解和参数获取缓存的key,
String key = CacheKey(method, args);
String cacheJson = redisTemplate.opsForValue().get(key);
joeClass<?> returnType = ReturnType();
adValue(cacheJson,returnType);
如果method的返回类型是List<Ur>,上⾯的⽅法ReturnType() 的返回值只是Class<java.util.List>,所以反序列化的结果是ArrayList<HashMap>类型的,⽽并不是List<Ur>类型。
woolly另外,上⾯为了简化代码没有判断缓存是否有值,和没有缓存执⾏⽬标⽅法的并添加缓存的代码。
next
后来看了⼀下jackson的代码注释,使⽤下列⽅法可以通⽤的解析json数据为带泛型的结果;
Method method = ((MethodSignature) Signature()).getMethod();
Object[] args = Args();
//根据⽅法注解和参数获取缓存的key,
String key = CacheKey(method, args);
//获取redis缓存的值,
String cacheJson = redisTemplate.opsForValue().get(key);
//带有泛型信息
Type genericReturnType = GenericReturnType();
//获取返回类的绑定信息
JavaType javaType = JavaType(genericReturnType);
adValue(cacheJson,javaType);
下⾯是JavaType(Type type)的代码
public static JavaType getJavaType(Type type) {
//判断是否带有泛型
if (type instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
//获取泛型类型
Class rowClass = (Class) ((ParameterizedType) type).getRawType();
JavaType[] javaTypes = new JavaType[actualTypeArguments.length];
for (int i = 0; i < actualTypeArguments.length; i++) {
workgroup/
/泛型也可能带有泛型,递归获取
javaTypes[i] = getJavaType(actualTypeArguments[i]);toho
}
return TypeFactory.defaultInstance().constructParametricType(rowClass, javaTypes);
chine是什么意思} el {
//简单类型直接⽤该类构建JavaType
Class cla = (Class) type;
return TypeFactory.defaultInstance().constructParametricType(cla, new JavaType[0]);
}
}
上⾯的⽅法经过测试可以解析任意层数,但是是递归实现,搞了半天没搞出来循环⽅式实现。有循环实现的求评论个链接或则代码。。。
另外把structParametricType()的源码注释贴下⾯
/**
* Factory method for constructing {@link JavaType} that
* reprents a parameterized type. For example, to reprent
* type <code>List<Set<Integer>></code>, you could
* call
*<pre>
* JavaType inner = structParametricType(Set.class, Set.class, Integer.class);
* structParametricType(ArrayList.class, List.class, inner);
*</pre>
qstr*<p>
arc
* The reason for first two arguments to be parate is that parameterization may
* apply to a super-type. For example, if generic type was instead to be
* constructed for <code>ArrayList<Integer></code>, the usual call would be:
*<pre>
* structParametricType(ArrayList.class, List.class, Integer.class);
*</pre>edl
* since parameterization is applied to {@link java.util.List}.
* In most cas distinction does not matter, but there are types where it does;
* one such example is parameterization of types that implement {@link java.util.Iterator}.
*<p>
* NOTE: type modifiers are NOT called on constructed type.
*
* @param rawType Actual type-erad type
* @param parameterTypes Type parameters to apply
*
* @since 2.5 NOTE: was briefly deprecated for 2.6
*/
觉得有⽤点个赞。
感谢信英文