New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gson does not deserialize interfaces, even with an InstanceCreator #411
Comments
Original comment by
|
Original comment by |
Original comment by |
Original comment by |
Original comment by |
Original comment by |
Original comment by |
Original comment by |
Original comment by |
The only solutions I have found were to do a |
This is a major bug. I have wasted 2 days into this till I came across this page. Google, please solve this problem or at least give an easier workaround |
This issue schould be prioritized. I need it soon 👍 |
Another encounter of this issue. https://stackoverflow.com/questions/49870055/deserializing-interface-data-using-gson-not-getting-the-value-back |
I can't even get this to work with a TypeAdaptor. It is complicated by the fact that the interface is implemented by an enum, which you cannot instantiate yourself. When I try to work around by having the TypeAdaptor return the enum value, it errors with: Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 13 path $.doctype So, I don't even have a work-around. |
A workaround for this can be to use a custom class SubtypeDeserializingAdapterFactory implements TypeAdapterFactory {
private final Map<Class<?>, Class<?>> subtypeMap;
public SubtypeDeserializingAdapterFactory(Map<Class<?>, Class<?>> subtypeMap) {
this.subtypeMap = subtypeMap;
}
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<?> raw = type.getRawType();
Class<?> mappedType = subtypeMap.get(raw);
if (mappedType == null) {
return null;
}
final TypeAdapter<T> serializationDelegate = gson.getDelegateAdapter(this, type);
@SuppressWarnings("unchecked")
final TypeAdapter<T> deserializationDelegate = (TypeAdapter<T>) gson.getAdapter(mappedType);
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
serializationDelegate.write(out, value);
}
@Override
public T read(JsonReader in) throws IOException {
return deserializationDelegate.read(in);
}
};
}
} You can then define the mapping from interface or abstract class to implementation class like this: interface MyInterface {
}
static class MyImplClass implements MyInterface {
int i;
@Override
public String toString() {
return "MyImplClass[" + i + "]";
}
}
public void test() {
Map<Class<?>, Class<?>> subtypeMap = new HashMap<>();
// Defines deserialization mapping from MyInterface -> MyImplClass
subtypeMap.put(MyInterface.class, MyImplClass.class);
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new SubtypeDeserializingAdapterFactory(subtypeMap))
.create();
System.out.println(gson.fromJson("{\"i\":2}", MyInterface.class));
} Note that this likely prevents the preference order of |
Original issue reported on code.google.com by
jason.po...@gmail.com
on 21 Feb 2012 at 2:33The text was updated successfully, but these errors were encountered: