aufrufen Ich bekomme ein JSON, das Feld "Feld" hat.
Wenn das "Feld" Daten enthält, gibt es ein OBJEKT, das viele (etwa 20) andere Felder enthält, die ebenfalls Objekte sind. Ich kann sie ohne Probleme deserialisieren.
Aber wenn "Feld" keine Daten hat, ist es ein leeres ARRAY (ich weiß, es ist verrückt, aber das ist die Antwort vom Server und ich kann es nicht ändern). Etwas wie folgt aus:Wie Standard-Deserialisierung mit Gson
Wenn leer:
"extras":[
]
hat einige Daten:
"extras": {
"22":{ "name":"some name" },
"59":{ "name":"some other name" },
and so on...
}
Also, wenn es, wenn keine Daten (leeres Array), bekomme ich natürlich die Ausnahme
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 4319
Ich habe versucht, benutzerdefinierte JavaDeserializer verwenden:
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;
}
}
}
Ich las die json die folgende Art und Weise
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);
Ich will nicht manuell alle 20 Felder deserialisiert (Ich weiß, das ist eine Option), ich möchte nur context.defaultDeserialize nennen (), oder etwas ähnliches.
Noch einmal: Ich habe keine Probleme deserializing normalen json, Erstellen von benutzerdefinierten Objekten, Registrierung von benutzerdefinierten TypeAdapters, benutzerdefinierte JavaDeserializers. Es funktioniert alles schon. Ich brauche nur eine Lösung für den Umgang mit Daten, die sowohl ARRAY als auch OBJECT sein können.
Danke für jede Hilfe.
======================
Die Antwort des Joey funktioniert perfekt. Genau das Richtige, nach dem ich gesucht habe. Ich poste meinen Code hier.
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;
}
}
};
}
}
Fügen Sie den Code ein, in dem Sie Daten deserialisieren, wenn Array verfügbar ist – waqaslam
Array kann nicht verfügbar sein. Es kann nur leer sein. Wenn ich das Array deserialisieren müsste, würde ich es im catch-Block machen. –