gson反序列化使用自定义方法扩展特定类的嵌套对象

o75abkj4  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(259)

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

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 = "";
}

如何初始化嵌套的 SomeNestedConfig nestedConfig 当我初始化 RuleSetConfigForm ? 有没有什么自动化的方法?

xbp102n0

xbp102n01#

这可以通过自定义 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);
}

相关问题