【问题标题】:Gson deserialize nested object that extend specific class using custom methodGson 使用自定义方法反序列化扩展特定类的嵌套对象
【发布时间】:2020-11-19 17:14:22
【问题描述】:

我有一个抽象类,如下所示

public abstract class IndexedPojo {
    List<String> keySet;

    public List<String> getKeySet() {
        return keySet;
    }

    public void setKeySet(List<String> keySet) {
        this.keySet = keySet;
    }
    public void setKeySet(JsonObject parameters) {
        this.keySet = new ArrayList<>(parameters.keySet());
    }
    public void setKeySet(Map<String,String> parameters) {
        this.keySet = new ArrayList<>(parameters.keySet());
    }
}

这个抽象类的目的是提供跟踪已在扩展它的类中初始化的变量的功能。为什么我需要这个?我正在为要在测试自动化项目中使用的表单建模 pojo 类。有些参数是可选的,如果它们没有被初始化,相应的表单元素不会被填充。目前我正在使用这种方法来创建扩展IndexedPojo类的类的实例:

public static <T extends IndexedPojo> T deserializeJsonTo(JsonObject parameters, Class<T> tClass) {
    Gson gson = new Gson();
    T instance = gson.fromJson(parameters, tClass);
    instance.setKeySet(parameters);
    return instance;
}

但现在的问题是一些嵌套的孩子也是extend IndexedPojo 的类,我想以同样的方式初始化它们。例如

public class RuleSetConfigForm extends IndexedPojo {
    @SerializedName("Key")
    SomeNestedConfig nestedConfig;    
}
public class SomeNestedConfig extends IndexedPojo {
    @SerializedName("Some Key")
    private String someOptionalParamater1 = "";

    @SerializedName("Some Key2")
    private String someOptionalParamater2 = "";

    @SerializedName("Some Key3")
    private String someOptionalParamater3 = "";
}

我如何在初始化RuleSetConfigForm 时初始化嵌套的SomeNestedConfig nestedConfig?有没有自动化的方式来做到这一点?

【问题讨论】:

    标签: java json gson deserialization pojo


    【解决方案1】:

    这可以使用自定义TypeAdapterFactory 解决,该TypeAdapterFactory 委托给默认适配器,然后调用您的IndexedPojo.setKeySet(...) 方法:

    class IndexedPojoTypeAdapterFactory implements TypeAdapterFactory {
      public static final IndexedPojoTypeAdapterFactory INSTANCE = new IndexedPojoTypeAdapterFactory();
    
      private IndexedPojoTypeAdapterFactory() { }
    
      public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // Only handle IndexedPojo and subclasses
        if (!IndexedPojo.class.isAssignableFrom(type.getRawType())) {
          return null;
        }
    
        // Get the default adapter as delegate
        // Cast is safe due to `type` check at method start
        @SuppressWarnings("unchecked")
        TypeAdapter<IndexedPojo> delegate = (TypeAdapter<IndexedPojo>) gson.getDelegateAdapter(this, type);
        // Cast is safe because `T` is IndexedPojo or subclass (due to `type` check at method start)
        @SuppressWarnings("unchecked")
        TypeAdapter<T> adapter = (TypeAdapter<T>) new TypeAdapter<IndexedPojo>() {
          @Override
          public void write(JsonWriter out, IndexedPojo value) throws IOException {
            delegate.write(out, value);
          }
    
          @Override
          public IndexedPojo read(JsonReader in) throws IOException {
            // Read JsonObject from JsonReader to be able to pass it to `IndexedPojo.setKeySet(...)`
            // afterwards
            // Note: JsonParser automatically parses in lenient mode, which cannot be disabled
            // Note: Might have to add handling for JSON null values
            JsonObject jsonObject = JsonParser.parseReader(in).getAsJsonObject();
            
            IndexedPojo value = delegate.fromJsonTree(jsonObject);
            value.setKeySet(jsonObject);
            return value;
          }
        };
    
        return adapter;
      }
    }
    

    然后在你的deserializeJsonTo(...) 方法中使用这个工厂:

    public static <T extends IndexedPojo> T deserializeJsonTo(JsonObject parameters, Class<T> tClass) {
      // Note: Could also store Gson instance in `static final` field
      Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(IndexedPojoTypeAdapterFactory.INSTANCE)
        .create();
      return gson.fromJson(parameters, tClass);
    }
    

    【讨论】:

    • 这很完美。多亏了你,我的代码变得更加灵活了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    相关资源
    最近更新 更多