/**
  * 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));
              }
            });
  }
Пример #3
0
  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);
    }
  }
Пример #4
0
  /**
   * 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);
 }