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(); | |
} | |
} | |
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?
@danielesegato https://github.com/rharter/auto-value-gson works with generics
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 ?