问题
I'm trying to deserialize some data with Gson (Java) and the API I'm pulling data from sometimes has data of the wrong type in a field. I.e. if I'm expecting an array of String
types, it might encounter a Boolean
.
Now I realize these are my current options:
- Always ignore the field from deserialization
- Create a custom
TypeAdapter
to do the deserialization and the catch the error and do something (like set the field tonull
)
However I'm asking if there's another way to easily make it so if there's an exception parsing a certain field, that Gson will just ignore that field. Something like an annotation on that field like @Skippable
or maybe a setting when using the GsonBuilder
to create a Gson
object?
Is anyone familiar with such a thing?
回答1:
It is not an easy task to handle properly all possible errors in JSON
and mismatches between payload and POJO
model. But we can try to implement com.google.gson.TypeAdapterFactory
interface and wrap all default TypeAdapter
s in try-catch
and skip invalid data. Example solution could look like this:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.setLenient()
.registerTypeAdapterFactory(new IgnoreFailureTypeAdapterFactory())
.create();
Entity entries = gson.fromJson(new FileReader(jsonFile), Entity.class);
System.out.println(entries);
}
}
class IgnoreFailureTypeAdapterFactory implements TypeAdapterFactory {
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
return createCustomTypeAdapter(delegate);
}
private <T> TypeAdapter<T> createCustomTypeAdapter(TypeAdapter<T> delegate) {
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
@Override
public T read(JsonReader in) throws IOException {
try {
return delegate.read(in);
} catch (Exception e) {
in.skipValue();
return null;
}
}
};
}
}
class Entity {
private Integer id;
private String name;
// getters, setters, toString
}
For example, above code prints:
Entity{id=null, name='1'}
for below JSON
payload:
{
"id": [
{
"a": "A"
}
],
"name": 1
}
See also:
- Same object referenced in two classes, duplicated instance after decode
来源:https://stackoverflow.com/questions/59655279/is-there-an-easy-way-to-make-gson-skip-a-field-if-theres-an-error-deserializing