I Retrofit 2.1.0 mit Konverter-Gson bin mit: 2.1.0 und separat Gson: 2.6.2 um die Serialisierung/Deserialisierung anpassen. Das Problem ist, dass meine POJOs hinter Schnittstellen versteckt sein sollten und ich gson mitteilen möchte, welche Klasse die deserialisierte Schnittstelle sein soll. Und nach der Deserialisierung/Serialisierung sollte Retrofit die Schnittstelle zurückgeben können. Es wäre gut, wenn ich die Vorteile von Generics nutzen und leicht eine Möglichkeit schaffen könnte, Gson oder Retrofit zu sagen, FooInterface zu FooClass zu serialisieren/deserialisieren.Gson deserialisieren Schnittstelle zu seiner Klasse Implementierung
Antwort
Ich gehe davon aus, dass Sie einen einzigen Deserializer für alle Ihre Schnittstellen und ihre jeweiligen Implementierungen erstellen möchten. Befolgen Sie diese Schritte bitte:
1. Erstellen Sie eine Basisschnittstelle, die von Ihren anderen App-Schnittstellen erweitert wird. Es ist erforderlich, einen einzelnen Deserializer für alle Ihre Schnittstellen und Implementierungsklassen zu erstellen.
public interface Convertable {
String getClassName();
}
2. Erstellen Sie Ihre Feature-Schnittstelle und Implementierungsklasse. Als Beispiel nennen wir sie FooInterface und FooClass. FooInterface sollte Convertierbare Schnittstelle erweitern.
FooInterface
public interface FooInterface extends Convertable {
}
FooClass
public class FooClass implements FooInterface {
// DISCRIMINATOR FIELD
private final String className;
private String field1;
private String field2;
public FooClass() {
this.className = getClass().getName();
}
public String getClassName() {
return className;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
}
anzumerken, dass der zurückgegebene Wert von getClassName() als Diskriminator Feld verwendet wird, die in Gson Deserializer (nächster Schritt) verwendet wird, um initialisiere Mehrweginstanz. Ich gehe davon aus, dass Ihre Serializer- und Deserializer-Klasse im selben Paket enthalten ist, auch wenn sie sich in verschiedenen Client- und Serveranwendungen befinden. Wenn nicht, dann müssen Sie die getClassInstance() - Implementierung ändern, aber das wäre ziemlich einfach.
3. Implementieren eines benutzerdefinierten Gson Serializer für alle Anwendungs
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
public class ConvertableDeserializer<T extends Convertable> implements JsonDeserializer<T> {
private static final String CLASSNAME = "className";
public T deserialize(final JsonElement jsonElement, final Type type,
final JsonDeserializationContext deserializationContext
) throws JsonParseException {
final JsonObject jsonObject = jsonElement.getAsJsonObject();
final JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
final String className = prim.getAsString();
final Class<T> clazz = getClassInstance(className);
return deserializationContext.deserialize(jsonObject, clazz);
}
@SuppressWarnings("unchecked")
public Class<T> getClassInstance(String className) {
try {
return (Class<T>) Class.forName(className);
} catch (ClassNotFoundException cnfe) {
throw new JsonParseException(cnfe.getMessage());
}
}
}
4. Register Deserializer mit Gson und initialisieren Retrofit
private static GsonConverterFactory buildGsonConverter() {
final GsonBuilder builder = new GsonBuilder();
// Adding custom deserializers
builder.registerTypeAdapter(FooInterface.class,
new ConvertableDeserializer<FooInterface>());
final Gson gson = builder.create();
return GsonConverterFactory.create(myGson);
}
public void initRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("REST_ENDPOINT")
.addConverterFactory(buildGsonConverter())
.client(httpClient)
.build();
}
Sie den Adapter für alle registrieren kann Ihrer Implementierungen, wenn Sie möchten, mit:
Weil Sie bereit sind, sich die Mühe nehmen fast die gesamte Domain Ebene zu duplizieren Schnittstellen mit der Implementierung Detail Ihrer Modelle zu verbergen, ich glaube, Sie meine Antwort erfrischende finden;)
Sie sollten AutoValue verwenden, um um Implementierungsdetails in Ihren Modellen zu verbergen. Die Art, wie es funktioniert, ist ziemlich einfach:
Sie schreiben eine abstrakte Klasse, und AutoValue implementiert es. Das ist alles da ist es; Es gibt buchstäblich keine Konfiguration.
Mit dieser Methode müssen Sie keine solche Menge an Boilerplate erstellen.
Und es gibt diese AutoValue-Erweiterung namens auto-value-gson, die Gson De/Serializer-Unterstützung aus der Box hinzugefügt.
Mit diesen einfachen Schritten denke ich, dass Ihre Code-Basis wesentlich verbessert wird.
Können Sie ein Beispiel geben? –
- 1. Deserialisieren einer Schnittstelle mit Gson?
- 2. Nullpointer Deserialisieren mit Gson
- 3. java.lang.NullPointerException beim Deserialisieren mit Gson
- 4. Dozer versucht, eine Klasse zu seiner Schnittstelle zuzuordnen
- 5. Deserialisieren Arraylist <Interface> mit Gson
- 6. Gson deserialisieren und serialisiert transiente Feld
- 7. Gson Deserialisieren verschachtelte Objekte mit InstanceCreator
- 8. Gson deserialisieren JSON Array mit mehreren Objekttypen
- 9. Gson ignorieren Null beim Deserialisieren von Objekt
- 10. Implementierung Schnittstelle Komparatoren
- 11. Problem Deserialisieren Bugzilla JSON mit Googles Gson
- 12. Schnittstelle Implementierung Callbacks - Management
- 13. google gson LinkedTreeMap-Klasse zu myclass
- 14. Implementierung Schnittstelle über mehrere Versionen
- 15. Implementierung Schnittstelle C#
- 16. mit explizite Schnittstelle Implementierung
- 17. Lambda Implementierung Schnittstelle
- 18. Deserialisieren eines JSON mit einer Liste von Objekten mit Gson
- 19. Funktion Implementierung Schnittstelle
- 20. Gson: Deserialize Json in abstrakte Klasse
- 21. Fehler TypeToken Gießen auf Typen, wenn sie mit Gson Deserialisieren
- 22. GSON: Entfernen Sie unnötiges übergeordnetes Objekt beim Deserialisieren
- 23. Web - Service - Proxy - Klasse zur Implementierung der Schnittstelle
- 24. Deserialisieren/Serialisieren von JSON mit Hilfe von RuntimeTypeAdapterFactory von Gson
- 25. Inject Schnittstelle Implementierung mit CDI
- 26. Pass und speichern Schnittstelle Implementierung
- 27. anonyme Klasse Umsetzung Schnittstelle
- 28. Wie man eine Schnittstelle zu seiner Unterschnittstelle wirft?
- 29. Deserialisieren von JSON-Arrays unter Verwendung von Gson
- 30. Implementierung einer Schnittstelle in Go
Ich werde diese Implementierung überprüfen und berichten. – toshkinl
Hast du es geschafft, es zu überprüfen? –
Ich erhalte "NPE" in der Zeile "final String className = prim.getAsString();' der Klasse 'ConvertibleDeserializer'. Und das ist offensichtlich. Mein JSON hat kein 'className'-Feld darin. – IlyaEremin