/** * 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 Flux<Object> decodeInternal( JsonObjectDecoder objectDecoder, Publisher<DataBuffer> inputStream, ResolvableType elementType, MimeType mimeType, Object[] hints) { Assert.notNull(inputStream, "'inputStream' must not be null"); Assert.notNull(elementType, "'elementType' must not be null"); TypeFactory typeFactory = this.mapper.getTypeFactory(); JavaType javaType = typeFactory.constructType(elementType.getType()); ObjectReader reader = this.mapper.readerFor(javaType); return objectDecoder .decode(inputStream, elementType, mimeType, hints) .map( dataBuffer -> { try { Object value = reader.readValue(dataBuffer.asInputStream()); DataBufferUtils.release(dataBuffer); return value; } catch (IOException e) { return Flux.error(new CodecException("Error while reading the data", e)); } }); }
public <T> T copy(T input) throws ObjectCopyException { try { byte[] bytes = mapper.writeValueAsBytes(input); TypeFactory tf = mapper.getTypeFactory(); JavaType type = tf.constructType(input.getClass()); return mapper.readValue(bytes, type); } catch (IOException e) { log.error("error in copying input", e); throw new ObjectCopyException("error in copying input", e); } }
/** * Invokes the given method on the {@code handler} passing the given params (after converting them * to beans\objects) to it. * * @param m the method to invoke * @param params the params to pass to the method * @return the return value (or null if no return) * @throws IOException on error * @throws IllegalAccessException on error * @throws InvocationTargetException on error */ protected JsonNode invoke(Method m, List<JsonNode> params) throws IOException, IllegalAccessException, InvocationTargetException { // debug log if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Invoking method: " + m.getName()); } // convert the parameters Object[] convertedParams = new Object[params.size()]; Type[] parameterTypes = m.getGenericParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { JsonParser paramJsonParser = mapper.treeAsTokens(params.get(i)); JavaType paramJavaType = TypeFactory.defaultInstance().constructType(parameterTypes[i]); convertedParams[i] = mapper.readValue(paramJsonParser, paramJavaType); } // invoke the method Object result = m.invoke(handler, convertedParams); Type genericReturnType = m.getGenericReturnType(); if (genericReturnType != null) { if (Collection.class.isInstance(result) && genericReturnType instanceof ParameterizedType) { try { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "attempting custom collection serialization"); } TypeFactory typeFactory = mapper.getTypeFactory(); Type actualTypeInCollection = ((ParameterizedType) genericReturnType).getActualTypeArguments()[0]; if (actualTypeInCollection instanceof TypeVariable) { // collection actually has a generic return type actualTypeInCollection = ((TypeVariable) actualTypeInCollection).getBounds()[0]; } JavaType rootType = typeFactory.constructCollectionType( Collection.class, typeFactory.constructType(actualTypeInCollection)); return valueToTree(mapper.writerWithType(rootType), result); } catch (Exception e) { LOGGER.log( Level.WARNING, "could not do custom collection serialization falling back to default", e); } } return mapper.valueToTree(result); } else { return null; } // return (genericReturnType!=null) ? mapper.valueToTree(result) : null; }
/** * Method that can be used to find out actual output (target) type; this usually can be determined * from type parameters, but may need to be implemented differently from programmatically defined * converters (which can not change static type parameter bindings). * * @param typeFactory * @since 2.2 */ @Override public JavaType getOutputType(TypeFactory typeFactory) { return typeFactory.constructType(ResponseCode.class); }
/** * Method that can be used to find out actual input (source) type; this usually can be determined * from type parameters, but may need to be implemented differently from programmatically defined * converters (which can not change static type parameter bindings). * * @param typeFactory * @since 2.2 */ @Override public JavaType getInputType(TypeFactory typeFactory) { return typeFactory.constructType(Integer.class); }
public static JavaType buildType(final Class<?> simple) { return typeFactory.constructType(simple); }