GSON ignore elements with wrong type
Define your model like this:
public class ApiResult {
private String error;
private String message;
private String resultCode;
private MyResultObject resultObj;
}
Then, create a TypeAdapterFactory for MyResultObject:
public class MyResultObjectAdapterFactory implements TypeAdapterFactory {
@Override
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType()!= MyResultObject.class) return null;
TypeAdapter<MyResultObject> defaultAdapter = (TypeAdapter<MyResultObject>) gson.getDelegateAdapter(this, type);
return (TypeAdapter<T>) new MyResultObjectAdapter(defaultAdapter);
}
public class MyResultObjectAdapter extends TypeAdapter<MyResultObject> {
protected TypeAdapter<MyResultObject> defaultAdapter;
public MyResultObjectAdapter(TypeAdapter<MyResultObject> defaultAdapter) {
this.defaultAdapter = defaultAdapter;
}
@Override
public void write(JsonWriter out, MyResultObject value) throws IOException {
defaultAdapter.write(out, value);
}
@Override
public MyResultObject read(JsonReader in) throws IOException {
/*
This is the critical part. So if the value is a string,
Skip it (no exception) and return null.
*/
if (in.peek() == JsonToken.STRING) {
in.skipValue();
return null;
}
return defaultAdapter.read(in);
}
}
}
Finally, register MyResultObjectAdapterFactory for Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new MyResultObjectAdapterFactory())
.create();
Now, when deserializing an ApiResult json with that Gson object, resultObj will be set null if it is a string.
I Hope this solves your problem =)
I've had a similar problem and came up with the following solution in the end:
In stead of trying to parse your element into a String
or Array
, try storing the data to a simple java.lang.Object
This prevents the parsing from crashing or throwing an exception.
eg. with GSON annotations the property of your model would look like this:
@SerializedName("resultObj")
@Expose
private java.lang.Object resultObj;
Next, when accessing your data at runtime, you can check if your resultObj
property is an instance of String
or not.
if(apiResultObject instanceof String ){
//Cast to string and do stuff
} else{
//Cast to array and do stuff
}
Original post: https://stackoverflow.com/a/34178082/3708094