Is there an easy way to make Gson skip a field if there's an error deserializing it?

↘锁芯ラ 提交于 2020-02-04 05:26:24

问题


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 to null)

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 TypeAdapters 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!