I have an interface class that looks like this.
public interface Species {
String name();
}
And a Human
class that implements @AutoValue
with a TypeAdapter.
@AutoValue
public abstract class Human implements Parcelable, Species {
public static Human create(String humanVariable) {
return new AutoValue_Human(humanVariable);
}
public static Human create(String name, String humanVariable) {
return new AutoValue_Human(name, humanVariable);
}
public static TypeAdapter<Human> typeAdapter(Gson gson) {
return new AutoValue_Human.GsonTypeAdapter(gson);
}
@SerializedName("name")
public abstract String name();
@Nullable
@SerializedName("human_variable")
public abstract String humanVariable();
@Override
public String name() {
return name();
}
}
When I pull down data from our API I get this error.
Unable to invoke no-args constructor for interface ..... Species. Register an InstanceCreator with Gson for this type may fix this problem.
I've been trying to figure out how to handle this but haven't had much luck.
I found some resources like this Serialize And Deserialize Interfaces but they don't use @AutoValue or auto-value-gson so not sure how to put everything together.
Any help would be much appreciate!
InstanceCreator
is not often used in Gson, suggested by Gson in such cases making some confusion, and usually can be replaced with type adapters (factories). TheInstanceCreator
interface can only create a default instance that won't be merged with the JSON you're trying to deserialize. For example:Output:
In this case you'd bind the
Species
interface with the defaultHuman
instance only. According to that,species.name()
would returnanonymous
only regardless the JSON (Gson internalReflectiveTypeAdapterFactory.Adapter
just skips all JSON fields (actually, it collects all fields first against the given field declared type, not an actual object type after theInstanceCreator
-created instance is created) because it's an interface -- not sure if it's not a bug though).What you really need here is the following steps:
com.ryanharter.auto.value:auto-value-gson:...
if you're not using yet.Human
type adapter factory created using theauto-value-gson
extension.Human
instance rather than aSpecies
instance.For example:
Output:
This is the solution I would recommend the most.
If, for any justified reason, you really need to deserialize a JSON as an unknown
Species
instance and resolve its type dynamically, you could create a more complex solution. One of its "classic" solutions is resolving an object type by its special JSON property (inspired by RuntimeTypeAdapterFactory coming from the Gson extras, not published as an artifact though):Output: