这是一个很好的问题,因为它隔离了一些应该很容易但实际上需要大量代码的东西。
首先,编写一个摘要,为您提供用于修改传出数据的钩子。此示例在 Gson 2.2 中使用了一个名为的新 API,该 API 允许您查找 Gson 默认使用的适配器。委托适配器非常方便,如果您只想调整标准行为。与完全自定义类型适配器不同,当您添加和删除字段时,它们将自动保持最新状态。TypeAdapterFactory
getDelegateAdapter()
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 树(由 表示),然后调用 hook 方法以允许子类自定义该树。与 使用 的反序列化类似。JsonElement
beforeWrite()
afterRead()
接下来,我们将其子类化为特定示例。为了说明这一点,我将在序列化映射时向其添加一个名为“size”的合成属性。对于对称性,当它被反序列化时,我会删除它。在实践中,这可以是任何自定义。MyClass
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的新TypeAdapter和TypeAdapterFactory类型非常强大,但它们也是抽象的,需要练习才能有效使用。希望这个例子有用!