Я получаю json, у которого есть поле field.
Если у "поля" есть данные, то есть OBJECT, который содержит много (около 20) других полей, которые также являются объектами. Я могу десериализировать их без проблем.
Но если "поле" не имеет данных, это пустой ARRAY (я знаю, что он сумасшедший, но ответ от сервера и я не могу его изменить).
Что-то вроде этого:
Когда пусто:
"extras":[
]
Имеет некоторые данные:
"extras": {
"22":{ "name":"some name" },
"59":{ "name":"some other name" },
and so on...
}
Итак, когда нет данных (пустой массив), я, очевидно, получаю исключение
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 4319
Я попытался использовать собственный JavaDeserializer:
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;
}
}
}
Я прочитал json следующим образом
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);
Я не хочу десериализовать все 20 полей вручную (я знаю, что это вариант), я просто хочу вызвать context.defaultDeserialize() или что-то в этом роде.
Еще раз: у меня нет никаких проблем десериализации нормального json, создания пользовательских объектов, регистрации пользовательских TypeAdapters, пользовательских JavaDeserializers. Все это уже работает. Мне нужно только некоторое решение для обработки данных, которые могут быть как ARRAY, так и OBJECT.
Спасибо за любую помощь.
======================
Ответ Джой работает отлично. Это правильно, что я искал.
Я отправлю свой код здесь.
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;
}
}
};
}
}