【问题标题】:Is there an easy way to make Gson skip a field if there's an error deserializing it?如果反序列化出现错误,是否有一种简单的方法可以让 Gson 跳过一个字段?
【发布时间】:2020-04-26 13:05:31
【问题描述】:

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

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

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

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

有没有人熟悉这种东西?

【问题讨论】:

    标签: java json gson deserialization json-deserialization


    【解决方案1】:

    正确处理JSON 中所有可能的错误以及有效负载与POJO 模型之间的不匹配并不是一件容易的事。但是我们可以尝试实现com.google.gson.TypeAdapterFactory 接口并将所有默认的TypeAdapters 包装在try-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
    }
    

    例如上面的代码打印:

    Entity{id=null, name='1'}
    

    对于JSON以下有效载荷:

    {
      "id": [
        {
          "a": "A"
        }
      ],
      "name": 1
    }
    

    另见:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      • 2017-06-21
      • 1970-01-01
      相关资源
      最近更新 更多