Ich serialisieren eine Unterklassen des UserInterface-Typs basierend auf dem Typ des Benutzers. Diese Unterklassen haben eine Liste. Rolle ist auch eine Schnittstelle. Ich habe benutzerdefinierte Gson Adapter geschrieben:Json: Deserializing Interface-Klasse mit List of Interface generischer Typ
public class InterfaceAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> {
public JsonElement serialize(T object, Type interfaceType, JsonSerializationContext context) {
final JsonObject wrapper = new JsonObject();
wrapper.addProperty("type", object.getClass().getName());
wrapper.add("data", context.serialize(object));
return wrapper;
}
public T deserialize(JsonElement elem, Type interfaceType, JsonDeserializationContext context) throws JsonParseException {
final JsonObject wrapper = (JsonObject) elem;
final JsonElement typeName = get(wrapper, "type");
final JsonElement data = get(wrapper, "data");
final Type actualType = typeForName(typeName);
return context.deserialize(data, actualType);
}
private Type typeForName(final JsonElement typeElem) {
try {
return Class.forName(typeElem.getAsString());
} catch (ClassNotFoundException e) {
throw new JsonParseException(e);
}
}
private JsonElement get(final JsonObject wrapper, String memberName) {
final JsonElement elem = wrapper.get(memberName);
if (elem == null) throw new JsonParseException("no '" + memberName + "' member found in what was expected to be an interface wrapper");
return elem;
}
}
Das Problem ist jedoch, dass ich Fehler: Caused by: java.lang.UnsupportedOperationException: Interface can't be instantiated! Interface name: Domain.Users.role.Role
. Ich weiß, was das Problem ist. Gson weiß nicht, welche konkrete Implementierung zur Instanziierung gewählt werden sollte. Wie kann ich Gson mitteilen, welche Klasse instanziiert werden soll? Hier
ist voll Stacktrace:
FATAL EXCEPTION: main
Process: org.ucomplex.ucomplex, PID: 346
java.lang.RuntimeException: Unable to create application org.ucomplex.ucomplex.Common.base.UCApplication: java.lang.RuntimeException: Unable to invoke no-args constructor for ? extends org.ucomplex.ucomplex.Domain.Users.role.Role. Register an InstanceCreator with Gson for this type may fix this problem.
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4729)
at android.app.ActivityThread.access$1600(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5442)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
Caused by: java.lang.RuntimeException: Unable to invoke no-args constructor for ? extends org.ucomplex.ucomplex.Domain.Users.role.Role. Register an InstanceCreator with Gson for this type may fix this problem.
at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:226)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:210)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:952)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.deserialize(TreeTypeAdapter.java:162)
at org.ucomplex.ucomplex.Domain.Users.InterfaceAdapter.deserialize(InterfaceAdapter.java:36)
at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at com.google.gson.Gson.fromJson(Gson.java:801)
at com.google.gson.Gson.fromJson(Gson.java:773)
at org.ucomplex.ucomplex.Common.FacadePreferences.getUserDataFromPref(FacadePreferences.java:49)
at org.ucomplex.ucomplex.Common.base.UCApplication.onCreate(UCApplication.java:52)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1014)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4726)
at android.app.ActivityThread.access$1600(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5442)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
Caused by: java.lang.UnsupportedOperationException: Interface can't be instantiated! Interface name: org.ucomplex.ucomplex.Domain.Users.role.Role
at com.google.gson.internal.UnsafeAllocator.assertInstantiable(UnsafeAllocator.java:117)
at com.google.gson.internal.UnsafeAllocator.access$000(UnsafeAllocator.java:31)
at com.google.gson.internal.UnsafeAllocator$1.newInstance(UnsafeAllocator.java:49)
at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:223)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:210)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:952)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.deserialize(TreeTypeAdapter.java:162)
at org.ucomplex.ucomplex.Domain.Users.InterfaceAdapter.deserialize(InterfaceAdapter.java:36)
at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at com.google.gson.Gson.fromJson(Gson.java:801)
at com.google.gson.Gson.fromJson(Gson.java:773)
at org.ucomplex.ucomplex.Common.FacadePreferences.getUserDataFromPref(FacadePreferences.java:49)
at org.ucomplex.ucomplex.Common.base.UCApplication.onCreate(UCApplication.java:52)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1014)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4726)
at android.app.ActivityThread.access$1600(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5442)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
EDIT: Diese Frage als Duplikat markiert wurde. Die markierte Frage beantwortet jedoch die Deserialisierung des Schnittstellentyps (und nicht auf die intelligenteste Weise). Mein Problem ist nicht darin. Ich weiß, wie man den Top-Level-Interface-Typ deserialisiert. In meinem Fall habe ich Base-Implementierung der Schnittstelle, die eine Liste eines anderen Schnittstellentyps hat. Diese Klasse wird für die Komposition verwendet. Picture this:
interface IA {}
interface IR {}
class R1 implements IR {}
class R2 implements IR {}
class A1 implements IA {
private List<IR> list;
}
class A2 implements IA {
private A1 member;
}
class A3 implements IA {
private A1 member;
}
Problem entsteht, während private List<IR> list;
deserilizing.
@chunjef wahr, aber ich weiß nicht wirklich, was ist InstanceCreator und wie man wenden Sie es auf meinen Fall an. Das ist das Problem. – Sermilion
Vielleicht wird dies [http://stackoverflow.com/questions/16396904/using-gson-with-interface-types] helfen. – chunjef
@chunjef diese Frage ist verwandt. Meine Frage geht um eine Stufe anders.Ich habe Interface-Typ, der List und der Fehler ist auf der zweiten Ebene. –
Sermilion