使用TypeAdapter为对象中的一个变量(多个变量)提供Gson自定义Seralizer

MountainX:

我已经看到了许多使用自定义TypeAdapter的简单示例。最有用的是Class TypeAdapter<T>但这还没有回答我的问题。

我想自定义对象中单个字段的序列化,并让默认的Gson机制负责其余的工作。

出于讨论目的,我们可以使用该类定义作为我希望序列化的对象的类。我想让Gson序列化基类的前两个类成员以及所有公开的成员,并且我想为如下所示的第3个和最后一个类成员进行自定义序列化。

public class MyClass extends SomeClass {

@Expose private HashMap<String, MyObject1> lists;
@Expose private HashMap<String, MyObject2> sources;
private LinkedHashMap<String, SomeClass> customSerializeThis;
    [snip]
}
杰西·威尔逊(Jesse Wilson):

这是一个很好的问题,因为它隔离了一些应该很容易但实际上需要大量代码的东西。

首先,编写一个摘要TypeAdapterFactory,为您提供钩子以修改传出数据。本示例在Gson 2.2中使用了一个新API,该API getDelegateAdapter()允许您查找Gson默认情况下将使用的适配器。如果您只想调整标准行为,则委托适配器非常方便。并且与完全自定义类型的适配器不同,在添加和删除字段时,它们将自动保持最新状态。

public abstract class CustomizedTypeAdapterFactory<C>
    implements TypeAdapterFactory {
  private final Class<C> customizedClass;

  public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
    this.customizedClass = customizedClass;
  }

  @SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
  public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    return type.getRawType() == customizedClass
        ? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
        : null;
  }

  private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
    final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
    final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
    return new TypeAdapter<C>() {
      @Override public void write(JsonWriter out, C value) throws IOException {
        JsonElement tree = delegate.toJsonTree(value);
        beforeWrite(value, tree);
        elementAdapter.write(out, tree);
      }
      @Override public C read(JsonReader in) throws IOException {
        JsonElement tree = elementAdapter.read(in);
        afterRead(tree);
        return delegate.fromJsonTree(tree);
      }
    };
  }

  /**
   * Override this to muck with {@code toSerialize} before it is written to
   * the outgoing JSON stream.
   */
  protected void beforeWrite(C source, JsonElement toSerialize) {
  }

  /**
   * Override this to muck with {@code deserialized} before it parsed into
   * the application type.
   */
  protected void afterRead(JsonElement deserialized) {
  }
}

上面的类使用默认的序列化来获取JSON树(以表示JsonElement),然后调用hook方法beforeWrite()以允许子类自定义该树。与相同的反序列化afterRead()

接下来,我们将其子类化为特定MyClass示例。为了说明这一点,我将在序列化时向地图添加一个名为“ size”的综合属性。为了对称起见,我会在反序列化时将其删除。实际上,这可以是任何定制。

private class MyClassTypeAdapterFactory extends CustomizedTypeAdapterFactory<MyClass> {
  private MyClassTypeAdapterFactory() {
    super(MyClass.class);
  }

  @Override protected void beforeWrite(MyClass source, JsonElement toSerialize) {
    JsonObject custom = toSerialize.getAsJsonObject().get("custom").getAsJsonObject();
    custom.add("size", new JsonPrimitive(custom.entrySet().size()));
  }

  @Override protected void afterRead(JsonElement deserialized) {
    JsonObject custom = deserialized.getAsJsonObject().get("custom").getAsJsonObject();
    custom.remove("size");
  }
}

最后,通过Gson使用新类型的适配器创建一个自定义实例来将它们放在一起

Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(new MyClassTypeAdapterFactory())
    .create();

Gson的新TypeAdapterTypeAdapterFactory类型非常强大,但它们也是抽象的,需要进行实践才能有效使用。希望您发现此示例有用!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

查找使用一个属性自定义列表中的对象的的indexOf

在gson中使用自定义typeadapter,jsonwriter添加对象

用于对象中一个变量的Gson自定义脱盐器

如何返回一个不是实体的对象列表,并添加一个自定义变量,该变量将从休眠查询中的属性文件中获取?

在sympy中定义一个变量为常量

为多个类型变量定义一个约束

动态SQL从自定义@Column获取一个值到结果变量中

我们可以继承另一个类中的一个类中定义的自定义变量吗?

使用特定的变量名称时,对象分解为我提供了一个NaN值

如何在另一个组列表(groupby)中实现组列表。是否可以在dart自定义对象中使用多个哈希码和operator ==

为Google GSON添加自定义TypeAdapterFactory,以检测注释的使用,以动态返回自定义TypeAdapter

使用object的一个元素为自定义创建的对象ArrayList重载indexOf()

编写自定义函数以基于另一个表转换数据框中的变量类

在另一个字符串中查找自定义变量字符串

从json对象中为JQplot编写一个自定义数组

自定义对象属性-多个基本变量或对象数组

更新自定义变量并从另一个Jenkins作业访问它

在另一个自定义UIView中设置/更改嵌套自定义UIView的变量

在案例中为VBA中的一个文本框定义多个工作表的工作表和变量

在stargazer中使用ci.custom的自定义置信区间,用于一个变量模型

在 Django 中为模型定义另一个变量时使用一个变量

获取一个对象在多个变量中各自的排名

在一个内部定义多个变量

“描述(熊猫)”多个变量为一个变量

如何从自定义类型开始一个空变量?

“ValueError:没有为任何变量提供梯度”存在层中的自定义函数

在同一 Jenkins 管道中的下一个新代理中,如何在上一个结束的代理中获取自定义环境变量(使用 AWS 代码提交 Jenkins 项目)

尝试输出一个自定义 powershell 对象,我可以在其中对齐包含 Category:Description 的两个不同变量的每一行

棒棒糖图:使用 R 根据数据框中的另一个变量根据变量自定义颜色和棒棒糖高度