fromjson - java gson to list
Usando genéricos con GSON (3)
Creo que la primera respuesta no es señalar la solución real: también DEBES pasar la instancia de Clase junto con T, así:
public T decode(String json, Class<T> cls) {
Gson gson = new Gson();
return gson.fromJson(json, cls);
}
Esto se debe a que ''T'' aquí es un tipo VARIABLE, no una referencia de tipo; y solo lo utiliza el compilador para agregar conversiones implícitas y verificar la compatibilidad de tipos. Pero si pasas clase real se puede utilizar; y el compilador verificará la compatibilidad de tipos para reducir la posibilidad de desajuste.
Alternativamente, puede tomar TypeToken y pasarlo; pero TypeToken debe construirse con tipo real, no con una variable de tipo; Tipo de variable es de poca utilidad aquí. Pero si desea envolver cosas, no querría que la persona que llama use TypeToken (que es un tipo de Gson).
El mismo mecanismo de envoltura funcionaría con otras librerías como Jackson, que mencionaste.
Estoy usando GSON para decodificar JSON en un objeto de tipo T, por ejemplo
public T decode(String json) {
Gson gson = new Gson();
return gson.fromJson(json, new TypeToken<T>() {}.getType());
}
Sin embargo, esto devuelve una excepción -
java.lang.AssertionError: Tipo inesperado. Se esperaba uno de: java.lang.reflect.ParameterizedType, java.lang.reflect.GenericArrayType, pero se obtuvo: sun.reflect.generics.reflectiveObjects.TypeVariableImpl, para el token de tipo: T
Pensé que al usar TypeToken evité el borrado de tipo.
¿Me equivoco?
Gracias
En primer lugar, no veo cómo es útil envolver así a Gson.
En cuanto a su problema, la información sobre el tipo genérico T
sí no está disponible durante el tiempo de ejecución. Ha sido borrado Solo está disponible durante el tiempo de compilación. Desea parametrizarlo con el tipo real, como new TypeToken<List<String>>
.
Debido a la falta de genéricos reificados en Java (no es posible hacer una T t = new T()
), Gson se ve obligado a usar el enfoque TypeToken
, como puede ver. De lo contrario, Gson lo habría hecho de una manera mucho más elegante.
Para poder pasar el tipo real, tienes que reinventar lo mismo que TypeToken
ya está haciendo. Y esto no tiene sentido :) Solo reutilizalo o solo usa Gson directamente sin envolverlo en alguna clase de ayuda como esa.
Mi solución a esto fue usar el analizador json y dividirlo en pedazos
public static <TT> PushObj<TT> fromJSON(String json, Class<TT> classType)
{
JsonObject jObj = new JsonParser().parse(json).getAsJsonObject();
String type = jObj.get("type").getAsString();
JsonObject job = jObj.get("object").getAsJsonObject();
TT obj = new Gson().fromJson(job, classType);
return new PushObj<TT>(type, obj);
}
Donde la estructura del objeto es: {Cadena: Tipo, Genérico: Objeto}
Y las variables son: jObj es el JSONObject de la cadena pasada y el trabajo es el JSONObject del objeto genérico
Así que usé el analizador json para obtener el tipo por separado y la reflexión para el objeto.