krebernisak
8/8/2014 - 6:09 PM

A Gson TypeAdapterFactory which allows serialization of @AutoValue types. Apache 2 licensed.

A Gson TypeAdapterFactory which allows serialization of @AutoValue types. Apache 2 licensed.

import com.google.auto.value.AutoValue;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {
  public static void main(String... args) {
    Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(new AutoValueAdapterFactory())
        .create();
    Test inTest = Test.of("John", "Doe", 100);
    System.out.println("IN: " + inTest);
    String json = gson.toJson(inTest);
    System.out.println("JSON: " + json);
    Test outTest = gson.fromJson(json, Test.class);
    System.out.println("OUT: " + outTest);
  }

  @AutoValue @AutoGson
  public abstract static class Test {
    public static Test of(String firstName, String lastName, int age) {
      return new AutoValue_Main_Test(firstName, lastName, age);
    }

    public abstract String firstName();
    public abstract String lastName();
    public abstract int age();
  }
}

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;

public final class AutoValueAdapterFactory implements TypeAdapterFactory {
  @SuppressWarnings("unchecked")
  @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<? super T> rawType = type.getRawType();
    if (!rawType.isAnnotationPresent(AutoGson.class)) {
      return null;
    }

    String packageName = rawType.getPackage().getName();
    String className = rawType.getName().substring(packageName.length() + 1).replace('$', '_');
    String autoValueName = packageName + ".AutoValue_" + className;

    try {
      Class<?> autoValueType = Class.forName(autoValueName);
      return (TypeAdapter<T>) gson.getAdapter(autoValueType);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("Could not load AutoValue type " + autoValueName, e);
    }
  }
}
import com.google.auto.value.AutoValue;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Marks an {@link AutoValue @AutoValue}-annotated type for proper Gson serialization.
 * <p>
 * This annotation is needed because the {@linkplain Retention retention} of {@code @AutoValue}
 * does not allow reflection at runtime.
 */
@Target(TYPE)
@Retention(RUNTIME)
public @interface AutoGson {
}