「フィールド」フィールドを持つjsonを取得します。
「フィールド」にデータがある場合、オブジェクトでもある多くの (約 20) 他のフィールドを持つ OBJECT があります。問題なくデシリアライズできます。
しかし、「フィールド」にデータがない場合、それは空の 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 のデシリアライズ、カスタム オブジェクトの作成、カスタム TypeAdapter の登録、カスタム 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;
}
}
};
}
}