Estoy escribiendo un código que se utilizará para recuperar recursos de un sitio web. Todo tipo de ve así:¿Cómo puedo usar Google GSON para deserializar una matriz JSON en una Colección de tipo genérico?
public Collection<Project> getProjects() {
String json = getJsonData(methods.get(Project.class)); //Gets a json list, ie [1, 2, 3, 4]
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<Project>>() {}.getType();
return gson.fromJson(json, collectionType);
}
Así que, naturalmente traté abstrayéndolo usando genéricos de Java.
/*
* Deserialize a json list and return a collection of the given type.
*
* Example usage: getData(AccountQuota.class) -> Collection<AccountQuota>
*/
@SuppressWarnings("unchecked")
public <T> Collection<T> getData(Class<T> cls) {
String json = getJsonData(methods.get(cls)); //Gets a json list, ie [1, 2, 3, 4]
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<T>>(){}.getType();
return (Collection<T>) gson.fromJson(json, collectionType);
}
Sin embargo, la versión genérica del código no funciona del todo.
public void testGetItemFromGetData() throws UserLoginError, ServerLoginError {
Map<String,String> userData = GobblerAuthenticator.authenticate("[email protected]", "mypassword");
String client_key = userData.get("client_key");
GobblerClient gobblerClient = new GobblerClient(client_key);
ArrayList<Project> machines = new ArrayList<Project>();
machines.addAll(gobblerClient.getData(Project.class));
assertTrue(machines.get(0).getClass() == Project.class);
Log.i("Machine", gobblerClient.getData(Project.class).toString());
}
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.gobbler.synchronization.Machine
at com.gobblertest.GobblerClientTest.testGetItemFromGetData(GobblerClientTest.java:53)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551)
la clase en cuestión:
import java.util.Map;
public class Project {
private int total_bytes_stored;
private String name;
private String user_data_guid;
private int seqnum;
private String guid;
private Map current_checkpoint;
private Map<String, String> upload_folder;
// TODO: schema_version
private boolean deleted;
// TODO: download_folders
public Project() {} // No args constructor used for GSON
}
No estoy muy familiarizado con todos los detalles de los genéricos de Java y los componentes internos GSON y mi búsqueda no ha sido particularmente informativo. Aquí hay un montón de preguntas sobre SO, pero la mayoría se refieren a métodos de implementación como el original que tuve. Y el GSON docs no parece cubrir este caso particular. Entonces, de nuevo, ¿cómo puedo usar Google GSON para deserializar una matriz JSON en una Colección de tipo genérico?
bueno para escuchar, si sólo para dar cierre. Entiendo que el tema probablemente esté un poco involucrado, pero ¿puedes explicar por qué brevemente? –
Para compatibilidad con versiones anteriores y simplicidad de implementación, la JVM no conoce los tipos detrás de los parámetros de tipo en el tiempo de ejecución. Por lo general, no te importa, pero esta es una de las situaciones en las que lo haces. La web tiene muchos artículos sobre el "borrado de Java" que tienen más detalles. –
En realidad, puede, consulte la respuesta dada por @jevon http://stackoverflow.com/a/12576189/608805 – raukodraug