java Google Gson - deserialize list <class> object? (tipo genérico)




6 Answers

Otra forma es usar una matriz como tipo, por ejemplo:

MyClass[] mcArray = gson.fromJson(jsonString, MyClass[].class);

De esta manera, evitará toda la molestia con el objeto Tipo, y si realmente necesita una lista, siempre puede convertir la matriz en una lista de la siguiente manera:

List<MyClass> mcList = Arrays.asList(mcArray);

En mi humilde opinión esto es mucho más legible.

Y para que sea una lista real (que se puede modificar, consulte las limitaciones de Arrays.asList() ) y luego haga lo siguiente:

List<MyClass> mcList = new ArrayList<>(Arrays.asList(mcArray));
java json generics gson

Quiero transferir un objeto de lista a través de Google Gson, pero no sé cómo deserializar tipos genéricos.

Lo que intenté después de mirar this (respuesta de BalusC):

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

pero luego aparece un error en el eclipse que dice "El nuevo tipo de lista () {} debe implementar el método abstracto heredado ..." y si uso una solución rápida, obtengo un monstruo de más de 20 talones de métodos.

Estoy bastante seguro de que hay una solución más fácil, ¡pero parece que no puedo encontrarla!

Editar:

Ahora tengo

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

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

Sin embargo, obtengo la siguiente excepción en la línea "fromJson":

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)

Capturo JsonParseExceptions y el "resultado" no es nulo.

Verifiqué listType con el depurador y obtuve lo siguiente:

  • Tipo de lista
    • args = ListOfTypes
      • list = null
      • resolverTypes = Tipo [1]
    • loader = PathClassLoader
    • ownerType0 = null
    • ownerTypeRes = null
    • rawType = Class (java.util.ArrayList)
    • rawTypeName = "java.util.ArrayList"

así que parece que la invocación "getClass" no funcionó correctamente. Alguna sugerencia...?

Edit2: He comprobado en la Guía del usuario de Gson . Menciona una excepción de tiempo de ejecución que debería ocurrir durante el análisis de un tipo genérico a Json. Lo hice "mal" (no se muestra arriba), como en el ejemplo, pero no obtuve esa excepción. Así que cambié la serialización como en la guía del usuario sugerida. Sin embargo, no ayudó.

Edit3: resuelto, ver mi respuesta a continuación.




Wep, otra forma de lograr el mismo resultado. Lo usamos por su legibilidad.

En lugar de hacer esta frase difícil de leer:

Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType();
List<YourClass> list = new Gson().fromJson(jsonArray, listType);

Cree una clase vacía que amplíe una lista de su objeto:

public class YourClassList extends ArrayList<YourClass> {}

Y úselo al analizar el JSON:

List<YourClass> list = new Gson().fromJson(jsonArray, YourClassList.class);



Como responde a mi pregunta original, he aceptado la respuesta de doc_180, pero si alguien vuelve a tener este problema, también responderé la segunda parte de mi pregunta:

El NullPointerError que describí no tenía nada que ver con la Lista en sí, ¡sino con su contenido!

La clase "MyClass" no tenía un constructor "no args", y ninguno tenía su superclase. Una vez que agregué un simple constructor "MyClass ()" a MyClass y su superclase, todo funcionó bien, incluida la serialización y deserialización de listas según lo sugerido por doc_180.




Desde Gson 2.8 , podemos crear una función util como

public <T> List<T> getList(String jsonArray, Class<T> clazz) {
    Type typeOfT = TypeToken.getParameterized(List.class, clazz).getType();
    return new Gson().fromJson(jsonArray, typeOfT);
}

Ejemplo usando

String jsonArray = ...
List<User> user = getList(jsonArray, User.class);



Quiero añadir para una posibilidad más. Si no desea utilizar TypeToken y desea convertir la matriz de objetos json en un ArrayList, puede proceder de la siguiente manera:

Si tu estructura json es como:

{

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

}

y tu estructura de clase es como:

public class ClassName implements Parcelable {

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

entonces puedes analizarlo como

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

Ahora puedes acceder a cada elemento del objeto className.




En la respuesta de My case @ uncaught_exceptions no funcionó, tuve que usar List.class lugar de java.lang.reflect.Type :

String jsonDuplicatedItems = request.getSession().getAttribute("jsonDuplicatedItems").toString();
List<Map.Entry<Product, Integer>> entries = gson.fromJson(jsonDuplicatedItems, List.class);



Related