/** * Return the Jackson {@link JavaType} for the specified type and context class. * * <p>The default implementation returns {@code typeFactory.constructType(type, contextClass)}, * but this can be overridden in subclasses, to allow for custom generic collection handling. For * instance: * * <pre class="code"> * protected JavaType getJavaType(Type type) { * if (type instanceof Class && List.class.isAssignableFrom((Class)type)) { * return TypeFactory.collectionType(ArrayList.class, MyBean.class); * } else { * return super.getJavaType(type); * } * } * </pre> * * @param type the generic type to return the Jackson JavaType for * @param contextClass a context class for the target type, for example a class in which the * target type appears in a method signature (can be {@code null}) * @return the Jackson JavaType */ protected JavaType getJavaType(Type type, Class<?> contextClass) { TypeFactory typeFactory = this.objectMapper.getTypeFactory(); if (type instanceof TypeVariable && contextClass != null) { ResolvableType resolvedType = resolveVariable((TypeVariable<?>) type, ResolvableType.forClass(contextClass)); if (resolvedType != ResolvableType.NONE) { return typeFactory.constructType(resolvedType.resolve()); } } return typeFactory.constructType(type); }
private ResolvableType resolveVariable(TypeVariable<?> typeVariable, ResolvableType contextType) { ResolvableType resolvedType; if (contextType.hasGenerics()) { resolvedType = ResolvableType.forType(typeVariable, contextType); if (resolvedType.resolve() != null) { return resolvedType; } } resolvedType = resolveVariable(typeVariable, contextType.getSuperType()); if (resolvedType.resolve() != null) { return resolvedType; } for (ResolvableType ifc : contextType.getInterfaces()) { resolvedType = resolveVariable(typeVariable, ifc); if (resolvedType.resolve() != null) { return resolvedType; } } return ResolvableType.NONE; }