Skip to content

Instantly share code, notes, and snippets.

@JakeWharton
Last active November 28, 2021 12:32
Show Gist options
  • Save JakeWharton/0d67d01badcee0ae7bc9 to your computer and use it in GitHub Desktop.
Save JakeWharton/0d67d01badcee0ae7bc9 to your computer and use it in GitHub Desktop.
A Gson TypeAdapterFactory which allows serialization of @autovalue types. Apache 2 licensed.
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 {
}
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 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();
}
}
@pedro-ribeiro
Copy link

Hi!

I'm trying to test this chunk of code and I'm always bumping into a no-args contructor problem.

Looking at the code generated by AutoValue, there is indeed no no-args constructor (as it should, afaik).

What am I missing?

Thanks!

@JakeWharton
Copy link
Author

@codedance That is far too presumptuous to work at scale.

@semanticer
Copy link

Is there a way how to use @SerializedName with AutoValue and this TypeAdapterFactory?

@efung
Copy link

efung commented May 19, 2016

@oldergod
Copy link

oldergod commented Sep 22, 2016

Also interested in adding SerializedName.

@lukasz-gosiewski
Copy link

lukasz-gosiewski commented Dec 5, 2016

Ok, what about Builders ? AutoValue for android support builder pattern, however when i use it with your @AutoGson it's giving me objects full of nulls. Is there any good way to go or i need to write my own solution ?

@danielesegato
Copy link

danielesegato commented Feb 3, 2017

Does this work with generics?

@AutoValue @AutoGson
public abstract static class Some<T> {
  public static Some <X> of(String firstName, String lastName, int age, X genericData) {
    return new AutoValue_Main_Test<>(firstName, lastName, age, genericData);
  }

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

When you do something like:

public class People {
  List<Some<Map<String,String>> someList;
}

And try to parse a "People" json, will the generic be resolved?

@Ajibola
Copy link

Ajibola commented Dec 12, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment