Ich möchte ein Listenobjekt über Google Gson übertragen, weiß jedoch nicht, wie generische Typen deserialisiert werden sollen.
Was ich versucht , nachdem bei der Suche diese (BalusC Antwort):
MyClass mc = new Gson().fromJson(result, new List<MyClass>(){}.getClass());
Aber dann erhalte ich in Eclipse die Fehlermeldung "Der Typ new List () {} muss die geerbte abstrakte Methode implementieren ..." und wenn ich eine schnelle Lösung verwende, erhalte ich ein Monster mit über 20 Methodenstubs.
Ich bin mir ziemlich sicher, dass es eine einfachere Lösung gibt, aber ich scheine sie nicht zu finden!
Bearbeiten:
Jetzt habe ich
Type listType = new TypeToken<List<MyClass>>()
{
}.getType();
MyClass mc = new Gson().fromJson(result, listType);
In der Zeile "fromJson" wird jedoch die folgende Ausnahme angezeigt:
java.lang.NullPointerException
at org.apache.harmony.luni.lang.reflect.ListOfTypes.length(ListOfTypes.java:47)
at org.apache.harmony.luni.lang.reflect.ImplForType.toString(ImplForType.java:83)
at java.lang.StringBuilder.append(StringBuilder.java:203)
at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:56)
at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:88)
at com.google.gson.JsonDeserializationVisitor.visitUsingCustomHandler(JsonDeserializationVisitor.java:76)
at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:106)
at com.google.gson.JsonDeserializationContextDefault.fromJsonArray(JsonDeserializationContextDefault.java:64)
at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:49)
at com.google.gson.Gson.fromJson(Gson.java:568)
at com.google.gson.Gson.fromJson(Gson.java:515)
at com.google.gson.Gson.fromJson(Gson.java:484)
at com.google.gson.Gson.fromJson(Gson.java:434)
Ich tun fangen JsonParseExceptions und „Ergebnis“ ist nicht null.
Ich habe listType mit dem Debugger überprüft und Folgendes erhalten:
- Listentyp
- args = ListOfTypes
- list = null
- ResolutionTypes = Typ [1]
- loader = PathClassLoader
- ownerType0 = null
- ownerTypeRes = null
- rawType = Klasse (java.util.ArrayList)
- rawTypeName = "java.util.ArrayList"
- args = ListOfTypes
Es scheint also, dass der Aufruf von "getClass" nicht richtig funktioniert hat. Irgendwelche Vorschläge...?
Edit2: Ich habe im Gson-Benutzerhandbuch nachgesehen . Es wird eine Laufzeitausnahme erwähnt, die beim Parsen eines generischen Typs für Json auftreten sollte. Ich habe es "falsch" gemacht (oben nicht gezeigt), genau wie im Beispiel, aber diese Ausnahme überhaupt nicht bekommen. Also habe ich die Serialisierung wie im Benutzerhandbuch vorgeschlagen geändert. Hat aber nicht geholfen.
Edit3: Gelöst, siehe meine Antwort unten.
TokenType
. Hast du es so versucht?Antworten:
Methode zum Deserialisieren der generischen Sammlung:
Da es in den Kommentaren von mehreren Personen erwähnt wurde, finden Sie hier eine Erklärung, wie die
TypeToken
Klasse verwendet wird. Die Konstruktionnew TypeToken<...>() {}.getType()
erfasst einen Typ zur Kompilierungszeit (zwischen<
und>
) in einem Laufzeitobjektjava.lang.reflect.Type
. Im Gegensatz zu einemClass
Objekt, das nur einen rohen (gelöschten) Typ darstellen kann, kann dasType
Objekt einen beliebigen Typ in der Java-Sprache darstellen, einschließlich einer parametrisierten Instanziierung eines generischen Typs.Die
TypeToken
Klasse selbst hat keinen öffentlichen Konstruktor, da Sie ihn nicht direkt erstellen sollen. Stattdessen erstellen Sie immer eine anonyme Unterklasse (daher die{}
, die ein notwendiger Bestandteil dieses Ausdrucks ist).Aufgrund des Löschens von Typen kann die
TypeToken
Klasse nur Typen erfassen, die zur Kompilierungszeit vollständig bekannt sind. (Das heißt, Sie können nichtnew TypeToken<List<T>>() {}.getType()
für einen Typparameter tunT
.)Weitere Informationen finden Sie in der Dokumentation zur
TypeToken
Klasse .quelle
{ "myObjectArray":[ {....} , {....} , {....} ] }
. Ich habe die Modelldatei erstellt{....}
. Wie kann ich diesen generischen Auflistungscode dazu bringen, nicht anzunehmen, dass mein Stammelement ein Array ist, ohne eine neue verschachtelte Objektdatei zu erstellen?Eine andere Möglichkeit besteht darin, ein Array als Typ zu verwenden, z.
Auf diese Weise vermeiden Sie den Ärger mit dem Type-Objekt. Wenn Sie wirklich eine Liste benötigen, können Sie das Array jederzeit in eine Liste konvertieren, indem Sie:
IMHO ist dies viel besser lesbar.
Und um es zu einer tatsächlichen Liste zu machen (die geändert werden kann, siehe Einschränkungen von
Arrays.asList()
), gehen Sie einfach wie folgt vor:quelle
MyClass
Wert nicht und er wird dynamisch definiert!T[] yourClassList = gson.fromJson(message, T[].class);
// kann nicht aus Typvariable auswählenmcList
in dieser Antwort nur das Ergebnis des Aufrufs anArrays.asList
. Diese Methode gibt eine Liste zurück, in der die meisten, wenn nicht alle optionalen Methoden nicht implementiert sind, und löst Ausnahmen aus. Beispielsweise können Sie dieser Liste kein Element hinzufügen. Wie aus der späteren Bearbeitung hervorgeht,Arrays.asList
gibt es Einschränkungen, undArrayList
wenn Sie es in eine tatsächliche Version einbinden, können Sie eine Liste abrufen, die in vielen Fällen nützlicher ist.Array.newInstance(clazz, 0).getClass()
wie in der Antwort von David Wood beschrieben verwenden .Siehe diesen Beitrag. Java Type Generic als Argument für GSON
Ich habe eine bessere Lösung dafür. Hier ist die Wrapper-Klasse für die Liste, damit der Wrapper den genauen Listentyp speichern kann.
Und dann kann der Code einfach sein:
quelle
mEntity.rulePattern
?Da
Gson 2.8
können wir util Funktion wie erstellenBeispiel mit
quelle
TypeToken#getParameterized
sieht viel besser aus als der Hack mit einer anonymen UnterklasseWep, ein weiterer Weg, um das gleiche Ergebnis zu erzielen. Wir verwenden es für seine Lesbarkeit.
Anstatt diesen schwer lesbaren Satz zu machen:
Erstellen Sie eine leere Klasse, die eine Liste Ihres Objekts erweitert:
Und verwenden Sie es beim Parsen des JSON:
quelle
Für Kotlin einfach:
oder hier ist eine nützliche Funktion:
Dann zu verwenden:
quelle
inline fun <reified T> buildType() = object : TypeToken<T>() {}.type!!
und rufen Sie sie mit dem Listentyp auf:buildType<List<YourMagicObject>>()
buildType
und rufen die Funktion auch mit dem generischen Typ auf? Ist das ein Tippfehler? - Das würde Arraylist <Arraylist <YourMagicObject >> erstellenBeispiel:
quelle
DevNG
obige Antwort, die 2 Jahre zuvor geschrieben wurde: stackoverflow.com/a/17300003/1339923 (und lesen Sie diese Antwort für Vorbehalte gegen diesen Ansatz)Da es meine ursprüngliche Frage beantwortet, habe ich die Antwort von doc_180 akzeptiert, aber wenn jemand erneut auf dieses Problem stößt, werde ich auch die 2. Hälfte meiner Frage beantworten:
Der von mir beschriebene NullPointerError hatte nichts mit der Liste selbst zu tun, sondern mit ihrem Inhalt!
Die "MyClass" -Klasse hatte keinen "no args" -Konstruktor und auch keine Superklasse. Nachdem ich MyClass und seiner Oberklasse einen einfachen Konstruktor "MyClass ()" hinzugefügt hatte, funktionierte alles einwandfrei, einschließlich der von doc_180 vorgeschlagenen Serialisierung und Deserialisierung der Liste.
quelle
Hier ist eine Lösung, die mit einem dynamisch definierten Typ arbeitet. Der Trick besteht darin, mit Array.newInstance () den richtigen Array-Typ zu erstellen.
quelle
class.cast()
die ungeprüfte Warnung vermeiden würden, die durch das Casting an verursacht wird(T)
. Oder, noch besser, kümmern Sie sich nicht um das Casting und verwenden Sie so etwas wieArrays.asList()
das Konvertieren von einem Array in einList<T>
. Es ist auch nicht erforderlich, eine Länge an zu übergebenArray.newInstance()
- ein Array der Größe Null ist gut genug, um es aufzurufengetClass()
.Ich möchte noch eine Möglichkeit hinzufügen. Wenn Sie TypeToken nicht verwenden und das JSON-Objektarray in eine ArrayList konvertieren möchten, können Sie wie folgt vorgehen:
Wenn Ihre JSON-Struktur wie folgt aussieht:
}}
und Ihre Klassenstruktur ist wie folgt:
dann können Sie es wie folgt analysieren:
Jetzt können Sie auf jedes Element des className-Objekts zugreifen.
quelle
In Beispiel 2 finden Sie Informationen zum Verständnis der Klasse 'Type' von Gson.
Beispiel 1: In diesem deserilizeResturant haben wir das Array Employee [] verwendet und die Details abgerufen
Beispiel 2:
quelle
Ich mochte die Antwort von kays1, konnte sie aber nicht implementieren. Also habe ich meine eigene Version mit seinem Konzept gebaut.
Verwendungszweck:
quelle
In meinem Fall hat die Antwort von @ uncaught_exceptions nicht funktioniert. Ich musste
List.class
stattdessen Folgendes verwendenjava.lang.reflect.Type
:quelle