繁体   English   中英

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

[英]Gson deserialize nested object that extend specific class using custom method

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

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初始化嵌套的SomeNestedConfig nestedConfig RuleSetConfigForm 有没有自动执行此操作的方法?

这可以通过使用委托给默认适配器的自定义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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM