529 Stimmen

Deserialisieren eines List<T>-Objekts mit Gson?

Ich möchte ein Listenobjekt über Google Gson übertragen, aber ich weiß nicht, wie man generische Typen deserialisiert.

Was ich versucht habe, nachdem ich mir este (die Antwort von BalusC):

MyClass mc = new Gson().fromJson(result, new List<MyClass>() {}.getClass());

aber dann bekomme ich in Eclipse die Fehlermeldung "The type new List<MyClass>() {} muss die geerbte abstrakte Methode implementieren..." und wenn ich eine schnelle Lösung verwende, erhalte ich ein Monster von über 20 Methoden-Stubs.

Ich bin mir ziemlich sicher, dass es eine einfachere Lösung gibt, aber ich scheine sie nicht zu finden!

Jetzt habe ich das hier:

Type listType = new TypeToken<List<MyClass>>() {}.getType();

MyClass mc = new Gson().fromJson(result, listType);

Ich erhalte jedoch die folgende Ausnahme bei der fromJson Linie:

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)

I hacer fangen JsonParseExceptions y result ist nicht null.

Ich überprüfte listType mit dem Debugger und erhielt folgendes Ergebnis:

  • list Type
    • args = ListOfTypes
      • list = null
      • resolvedTypes = Type[ 1 ]
    • loader = PathClassLoader
    • ownerType0 = null
    • ownerTypeRes = null
    • rawType = Class (java.util.ArrayList)
    • rawTypeName = "java.util.ArrayList"

Es scheint also, dass die getClass Aufrufen nicht richtig funktioniert hat. Irgendwelche Vorschläge...?

Ich habe die Gson Benutzerhandbuch . Es erwähnt eine Laufzeit-Ausnahme, die während des Parsens eines generischen Typs zu Json passieren sollte. Ich tat es "falsch" (nicht oben gezeigt), genau wie im Beispiel, aber nicht erhalten, dass Ausnahme überhaupt. Also änderte ich die Serialisierung wie im Benutzerhandbuch vorgeschlagen. Das hat aber nicht geholfen.

Editar:

Gelöst, siehe meine Antwort unten.

13voto

Chad Bingham Punkte 30660

Für Kotlin einfach:

import java.lang.reflect.Type
import com.google.gson.reflect.TypeToken
...
val type = object : TypeToken<List<T>>() {}.type

oder, hier ist eine nützliche Funktion:

fun <T> typeOfList(): Type {
    return object : TypeToken<List<T>>() {}.type
}

Dann, zu verwenden:

val type = typeOfList<YourMagicObject>()

7voto

kayz1 Punkte 6906
public static final <T> List<T> getList(final Class<T[]> clazz, final String json)
{
    final T[] jsonToObject = new Gson().fromJson(json, clazz);

    return Arrays.asList(jsonToObject);
}

Beispiel:

getList(MyClass[].class, "[{...}]");

6voto

jellyfish Punkte 7568

Da sie meine ursprüngliche Frage beantwortet, habe ich die Antwort von doc_180 akzeptiert, aber wenn jemand wieder auf dieses Problem stößt, werde ich auch die zweite Hälfte meiner Frage beantworten:

Der NullPointerError, den ich beschrieben habe, hatte nichts mit der Liste selbst zu tun, sondern mit ihrem Inhalt!

Die Klasse "MyClass" hatte keinen "no args"-Konstruktor, und auch ihre Oberklasse hatte keinen. Nachdem ich einen einfachen "MyClass()"-Konstruktor zu MyClass und seiner Superklasse hinzugefügt hatte, funktionierte alles einwandfrei, einschließlich der Serialisierung und Deserialisierung von Listen, wie von doc_180 vorgeschlagen.

6voto

David Wood Punkte 402

Hier ist eine Lösung, die mit einem dynamisch definierten Typ funktioniert. Der Trick besteht darin, den richtigen Typ des Arrays zu erstellen, indem man Array.newInstance() .

public static <T> List<T> fromJsonList(String json, Class<T> clazz) {
    Object [] array = (Object[])java.lang.reflect.Array.newInstance(clazz, 0);
    array = gson.fromJson(json, array.getClass());
    List<T> list = new ArrayList<T>();
    for (int i=0 ; i<array.length ; i++)
        list.add(clazz.cast(array[i]));
    return list; 
}

3voto

Apurva Sharma Punkte 191

Ich möchte eine weitere Möglichkeit hinzufügen. Wenn Sie TypeToken nicht verwenden wollen und ein Array von JSON-Objekten in eine ArrayList konvertieren wollen, dann können Sie wie folgt vorgehen:

Wenn Ihre json-Struktur ist wie:

{

"results": [
    {
        "a": 100,
        "b": "value1",
        "c": true
    },
    {
        "a": 200,
        "b": "value2",
        "c": false
    },
    {
        "a": 300,
        "b": "value3",
        "c": true
    }
]

}

und Ihre Klassenstruktur ist wie:

public class ClassName implements Parcelable {

    public ArrayList<InnerClassName> results = new ArrayList<InnerClassName>();
    public static class InnerClassName {
        int a;
        String b;
        boolean c;      
    }
}

dann können Sie es wie folgt analysieren:

Gson gson = new Gson();
final ClassName className = gson.fromJson(data, ClassName.class);
int currentTotal = className.results.size();

Jetzt können Sie auf jedes Element des className-Objekts zugreifen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X