Last active
January 1, 2025 22:35
-
-
Save JakeWharton/0d67d01badcee0ae7bc9 to your computer and use it in GitHub Desktop.
A Gson TypeAdapterFactory which allows serialization of @autovalue types. Apache 2 licensed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Does this work with generics?
When you do something like:
And try to parse a "People" json, will the generic be resolved?