Package br.com.caelum.vraptor.deserialization.gson

Source Code of br.com.caelum.vraptor.deserialization.gson.GsonDeserialization

package br.com.caelum.vraptor.deserialization.gson;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.caelum.vraptor.deserialization.Deserializer;
import br.com.caelum.vraptor.deserialization.Deserializes;
import br.com.caelum.vraptor.http.ParameterNameProvider;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.ResultException;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.io.CharStreams;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
*
* @author Renan Reis
* @author Guilherme Mangabeira
*/

@Deserializes({ "application/json", "json" })
@SuppressWarnings("rawtypes")
public class GsonDeserialization implements Deserializer {

  private static final Logger logger = LoggerFactory.getLogger(GsonDeserialization.class);

  private final ParameterNameProvider paramNameProvider;

  private final Collection<JsonDeserializer> adapters;

  private final HttpServletRequest request;

  public GsonDeserialization(ParameterNameProvider paramNameProvider, JsonDeserializers adapters, HttpServletRequest request) {
    this.paramNameProvider = paramNameProvider;
    this.adapters = adapters.getDeserializers();
    this.request = request;
  }

  public Object[] deserialize(InputStream inputStream, ResourceMethod method) {
    Class<?>[] types = getTypes(method);

    if (types.length == 0) {
      throw new IllegalArgumentException(
          "Methods that consumes representations must receive at least one argument");
    }

    Gson gson = getGson();

    Object[] params = new Object[types.length];
    String[] parameterNames = paramNameProvider.parameterNamesFor(method.getMethod());

    try {
      String content = getContentOfStream(inputStream);

      if(Strings.isNullOrEmpty(content)) {
        logger.debug("json with no content");
        return params;
      }

      logger.debug("json retrieved: {}", content);

      JsonParser parser = new JsonParser();
      JsonObject root = (JsonObject) parser.parse(content);

      for (int i = 0; i < types.length; i++) {
        String name = parameterNames[i];
        JsonElement node = root.get(name);
        if (isWithoutRoot(parameterNames, root)) {
          params[i] = gson.fromJson(root, types[i]);
          logger.info("json without root deserialized");
          break;
        }
        else if(node != null){
          params[i] = gson.fromJson(node, types[i]);
        }
        logger.debug("json deserialized: {}", params[i]);
      }
    } catch (Exception e) {
      throw new ResultException("Unable to deserialize data", e);
    }

    return params;
  }

  private boolean isWithoutRoot(String[] parameterNames, JsonObject root) {
    for(String parameterName : parameterNames) {
      if(root.get(parameterName) != null) return false;
    }
    return true;
  }

  protected Class<?>[] getTypes(ResourceMethod method) {
    Class<?> genericType = getSuperClassTypeArgument(method);

    if (genericType != null) {
      return parseGenericParameters(method.getMethod(), genericType);
    }

    return method.getMethod().getParameterTypes();
  }

  private Class<?>[] parseGenericParameters(Method method, Class<?> genericType) {
    Class<?>[] paramClasses = method.getParameterTypes();
    Type[] paramTypes = method.getGenericParameterTypes();

    Class<?>[] result = new Class<?>[paramTypes.length];

    for (int i = 0; i < paramTypes.length; i++) {
      Type paramType = paramTypes[i];

      if (paramType instanceof TypeVariable) {
        result[i] = genericType;
      } else {
        result[i] = paramClasses[i];
      }
    }

    return result;
  }

  private Class<?> getSuperClassTypeArgument(ResourceMethod method) {
    Type genericType = method.getResource().getType().getGenericSuperclass();

    if (genericType instanceof ParameterizedType) {
      return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
    }

    return null;
  }

  protected Gson getGson() {
    GsonBuilder builder = new GsonBuilder();

    for (JsonDeserializer<?> adapter : adapters) {
      builder.registerTypeHierarchyAdapter(getAdapterType(adapter), adapter);
    }

    return builder.create();
  }

  private Class<?> getAdapterType(JsonDeserializer<?> adapter) {
    Type[] genericInterfaces = adapter.getClass().getGenericInterfaces();
    ParameterizedType type = (ParameterizedType) genericInterfaces[0];
    Type actualType = type.getActualTypeArguments()[0];

    return (Class<?>) actualType;
  }

  private String getContentOfStream(InputStream input) throws IOException {
    String charset = getRequestCharset();
    logger.debug("Using charset {}", charset);
    return CharStreams.toString(new InputStreamReader(input, charset));
  }

  private String getRequestCharset() {
    String charset = Objects.firstNonNull(request.getHeader("Accept-Charset"), "UTF-8");
    return charset.split(",")[0];
  }
}
TOP

Related Classes of br.com.caelum.vraptor.deserialization.gson.GsonDeserialization

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.