如果反序列化出现错误,是否有一种简单的方法可以使 Gson 跳过该字段?

Rya*_*ull 5 java json gson deserialization json-deserialization

我正在尝试使用 Gson (Java) 反序列化一些数据,而我从中提取数据的 API 有时在字段中包含错误类型的数据。即,如果我期待一个String类型数组,它可能会遇到Boolean.

现在我意识到这些是我当前的选择:

  • 始终忽略反序列化中的字段
  • 创建一个自定义TypeAdapter来执行反序列化并捕获错误并执行某些操作(例如将字段设置为null

但是我问是否有另一种方法可以轻松实现,因此如果解析某个字段出现异常,Gson 将忽略该字段。像该字段上的注释之类的东西,或者可能是使用创建对象@Skippable时的设置?GsonBuilderGson

有人熟悉这样的事情吗?

Mic*_*ber 7

JSON正确处理有效负载和模型之间所有可能的错误和不匹配并不是一件容易的事POJO。但我们可以尝试实现com.google.gson.TypeAdapterFactory接口并包装所有默认值TypeAdaptertry-catch跳过无效数据。示例解决方案可能如下所示:

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
}
Run Code Online (Sandbox Code Playgroud)

例如,上面的代码打印:

Entity{id=null, name='1'}
Run Code Online (Sandbox Code Playgroud)

对于以下JSON有效负载:

{
  "id": [
    {
      "a": "A"
    }
  ],
  "name": 1
}
Run Code Online (Sandbox Code Playgroud)

也可以看看: