Obtengo un json que tiene el campo "campo".
Si el "campo" tiene datos, entonces hay un OBJETO que tiene muchos (alrededor de 20) otros campos que también son objetos. Puedo deserializarlos sin ningún problema.
Pero si "campo" no tiene datos, es un ARRAY vacío (sé que es una locura, pero esa es la respuesta del servidor y no puedo cambiarlo). Algo como esto:Cómo invocar la deserialización predeterminada con gson
Cuando está vacío:
"extras":[
]
tiene algunos datos:
"extras": {
"22":{ "name":"some name" },
"59":{ "name":"some other name" },
and so on...
}
Por lo tanto, cuando hay si no hay datos (matriz vacía), que, obviamente, obtener la excepción
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 4319
He intentado utilizar JavaDeserializer personalizado:
public class ExtrasAdapter implements JsonDeserializer<Extras> {
@Override
public Extras deserialize(JsonElement json, Type typeOf,
JsonDeserializationContext context) throws JsonParseException {
try {
JsonObject jsonObject = json.getAsJsonObject();
// deserialize normally
// the following does not work, as it makes recursive calls
// to the same function
//return context.deserialize(jsonObject,
// new TypeToken<Object>(){}.getType());
} catch (IllegalStateException e) {
return null;
}
}
}
leí el JSON de la siguiente manera
Gson gsonDecoder = new GsonBuilder().registerTypeAdapter(Extras.class, new ExtrasAdapter();
// httpResponse contains json with extras filed.
Reader reader = new InputStreamReader(httpResponse.getEntity().getContent());
Extras response = gsonDecoder.fromJson(reader, Extras.class);
no quiero deserializar los 20 campos manualmente (sé que esto es una opción), sólo quiero llamar context.defaultDeserialize (), o algo así.
Una vez más: no tengo problemas para deserializar json normal, crear objetos personalizados, registrar adaptadores de tipo personalizados, JavaDeserializers personalizados. Todo funciona ya. Solo necesito una solución para manejar datos, que pueden ser tanto ARRAY como OBJECT.
Gracias por cualquier ayuda.
======================
La respuesta del Joey funciona perfecto. Eso correcto lo que estaba buscando. Voy a publicar mi código aquí.
public class SafeTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
try {
delegate.write(out, value);
} catch (IOException e) {
delegate.write(out, null);
}
}
public T read(JsonReader in) throws IOException {
try {
return delegate.read(in);
} catch (IOException e) {
Log.w("Adapter Factory", "IOException. Value skipped");
in.skipValue();
return null;
} catch (IllegalStateException e) {
Log.w("Adapter Factory", "IllegalStateException. Value skipped");
in.skipValue();
return null;
} catch (JsonSyntaxException e) {
Log.w("Adapter Factory", "JsonSyntaxException. Value skipped");
in.skipValue();
return null;
}
}
};
}
}
pegue el código en el que está deserializando datos cuando el conjunto está disponible – waqaslam
La matriz no puede estar disponible. Solo puede estar vacío. Si tuviera que deserializar la matriz, lo haría en el bloque catch. –