Deserialización de tipos genéricos con GSON
Tengo algunos problemas con la implementación de Json Deserialization en mi aplicación de Android (con la biblioteca de Gson)
He hecho clase como esta
- Diferencia entre JSONObject y JSONArray
- ¿Cuál es la forma estándar de publicar el objeto JSON junto con el archivo utilizando MultipartEntityBuilder y el cliente HTTP en Android
- GSON. Cómo convertir json objeto a json array?
- cómo mostrar los datos json obtenidos en listview usando baseadapter
- Org.json.jsonarray no se puede convertir en error jsonobject
public class MyJson<T>{ public List<T> posts; }
Y la llamada de Deserialización es:
public class JsonDownloader<T> extends AsyncTask<Void, Void, MyJson<T>> { ... protected MyJson<T> doInBackground(Void... params) { ... Reader reader = new InputStreamReader(content); GsonBuilder gson = new GsonBuilder(); Type collectionType = new TypeToken<MyJson<T>>() {}.getType(); result = gson.create().fromJson(reader, collectionType); ... } }
El problema es que result.posts lista después de la llamada sostiene una matriz de objetos LinkedTreeMap (con valores correctos por lo que el problema es deserialización) en lugar de MyJson objetos. Cuando utilizo MyObject en lugar de T todo está funcionando bien y MyObject es correcto.
Entonces, ¿hay alguna manera de implementar la llamada de deserialización sin crear deserializador personalizado?
- Retrofit sigue olvidando mis cookies :( Android
- ¿Por qué recibo una respuesta vacía cuando mi aplicación android llama a mi API en mi servidor?
- Crear archivo JSON en línea y obtener URL
- Cómo crear dinámicamente grupos y childs en listview expandible desde json en android?
- Cómo cambiar el tipo de contenido de MappingJacksonHttpMessageConverter de application / json; charset = UTF-8 a application / json
- Reemplazar el analizador estándar de Android JSON para un mejor rendimiento?
- Importa datos de JSON o XML feed y crea una lista en Android
- Publicar Método utilizando Volley no funciona
¿Has probado?
gson.create().fromJson(reader, MyJson.class);
EDITAR
Después de leer esta publicación, parece que el uso de Type
es correcto. Creo que su problema es el uso de T
Usted debe recordar que con Java hay tipo de borrado. Esto significa que en tiempo de ejecución todas las instancias de T
son reemplazadas por Object
. Por lo tanto, en tiempo de ejecución lo que está pasando GSON es realmente MyJson<Object>
. Si lo intentaste con una clase concreta en lugar de <T>
creo que funcionaría.
Google Gson – deserializar lista <class> objeto? (Tipo genérico)
Debe especificar el tipo de T
en el momento de la deserialización. ¿Cómo se crearía tu List
de posts
si Gson
no sabía qué Type
de instancia? No puede quedarse para siempre. Por lo tanto, se proporciona el tipo T
como un parámetro de Class
.
Ahora suponiendo que el tipo de posts
era String
usted deserializaría MyJson<String>
como (también he añadido un parámetro String json
para la sencillez; leería de su reader
como antes):
doInBackground(String.class, "{posts: [\"article 1\", \"article 2\"]}"); protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) { GsonBuilder gson = new GsonBuilder(); Type collectionType = new TypeToken<MyJson<T>>(){}.getType(); MyJson<T> myJson = gson.create().fromJson(json, collectionType); System.out.println(myJson.getPosts()); // ["article 1", "article 2"] return myJson; }
Similarmente, para deserializar un MyJson
de objetos Boolean
doInBackground(Boolean.class, "{posts: [true, false]}"); protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) { GsonBuilder gson = new GsonBuilder(); Type collectionType = new TypeToken<MyJson<T>>(){}.getType(); MyJson<T> myJson = gson.create().fromJson(json, collectionType); System.out.println(myJson.getPosts()); // [true, false] return myJson; }
He asumido MyJson<T>
para que mis ejemplos sean como
public class MyJson<T> { public List<T> posts; public List<T> getPosts() { return posts; } }
Por lo tanto, si estaba buscando deserializar una List<MyObject>
, invocaría el método como
// assuming no Void parameters were required MyJson<MyObject> myJson = doInBackground(MyObject.class);
Así que la respuesta anterior no funcionó para mí, después de prueba y error que es cómo mi código terminó:
public class AbstractListResponse<T> { private List<T> result; public List<T> getResult() { return this.result; } }
La parte importante aquí es la firma del método, incluyendo el '<T>' a la izquierda.
protected <T> AbstractListResponse<T> parseAbstractResponse(String json, TypeToken type) { return new GsonBuilder() .create() .fromJson(json, type.getType()); }
Al llamar a Gson, el método recibe el TypeToken del objeto genérico.
TypeToken<AbstractListResponse<MyDTO>> typeToken = new TypeToken<AbstractListResponse<MyDTO>>() {}; AbstractListResponse<MyDTO> responseBase = parseAbstractResponse(json, typeToken);
Y finalmente el TypeToken puede usar MyDTO, o incluso un objeto simple, apenas MyDTO.