更简单的使用TypeAdapterFactory [英] Simpler use of TypeAdapterFactory

查看:105
本文介绍了更简单的使用TypeAdapterFactory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

AFAIK可以通过 TypeAdapterFactory 实现最灵活的gson定制,但它可能会变得不必要的复杂。它迫使我为每个处理过的类写入 read write ,但有时候只需要一种方法。此外,有时 JsonSerializer 和/或 JsonDeserializer 更容易编写,例如像这里。这导致我的这些问题:


  • 是否可以写一个 TypeAdapter which只需将其中一个方法委托给 List
  • 是否有可能以某种方式将 JsonSerializer 和/或 JsonDeserializer TypeAdapterFactory ?或者,他们是否有工厂?


解决方案

可以创建一个 TypeAdapter ,它委托它的一个方法。此用例是API的重要组成部分,并且有一个 getDelegateAdapter()方法。通过这个作为 getDelegateAdapter 的第一个参数,它将返回在当前工厂之后优先的适配器。

  TypeAdapterFactory immutableListFactory = new TypeAdapterFactory(){
@Override public< T> TypeAdapter< T> create(Gson gson,TypeToken< T> type){
if(!(type.getType()instanceof ParameterizedType)
||!type.getRawType()。equals(ImmutableList.class)){
返回null;
}

ParameterizedType parameterizedType =(ParameterizedType)type.getType();
TypeAdapter< T> delegate = gson.getDelegateAdapter(this,type);
TypeAdapter<?> elementAdapter = gson.getAdapter(
TypeToken.get(parameterizedType.getActualTypeArguments()[0]));
返回新的ImmutableListAdapter(delegate,elementAdapter);
}

类ImmutableListAdapter< E> extends TypeAdapter< ImmutableList< E>> {
private TypeAdapter< List< E>>代表;
private TypeAdapter< E>元件;

ImmutableListAdapter(TypeAdapter< List< E>>委托,TypeAdapter< E>元素){
this.delegate = delegate;
this.element = element;
}

@Override public void write(JsonWriter out,ImmutableList< E> value)throws IOException {
delegate.write(out,value);
}

@Override public ImmutableList< E> read(JsonReader in)抛出IOException {
if(in.peek()== JsonToken.NULL){
in.nextNull();
返回null;
}
ImmutableList.Builder< E> builder = ImmutableList.builder();
in.beginArray();
while(in.hasNext()){
builder.add(element.read(in));
}
in.endArray();
return builder.build();
}
}
};

您可以混合匹配 JsonSerializer / JsonDeserializer TypeAdapterFactory ,但不是直接。最简单的方法是回调Gson来序列化你的类中的子值。在这个例子中,我们将内部循环改为:

  while(in.hasNext()){
builder.add(来自Json的gson。< E>(in,elementType));

JsonSerializer / JsonDeserializer TypeAdapter 是从JSON到您的对象模型需要多少阶段。首先将 JsonSerializer / JsonDeserializer 对象转换为Gson的DOM模型( JsonElement 等),然后转换为您的对象模型。使用 TypeAdapter ,中间步骤被跳过。



这使得类型适配器代码在读写时有点棘手,所以你应该只选择优化代码。


AFAIK the most flexible gson customization is possible via TypeAdapterFactory, however it may get needlessly complicated. It forces me to write for each handled class both read and write, while sometimes only one method is really needed. Moreover, sometimes a JsonSerializer and/or JsonDeserializer were much easier to write, e.g. like here. This leads me to these questions:

  • Is it possible to write a TypeAdapter which simply delegates one of its methods (e.g. writing of ImmutableList to writing of List)?
  • Is it possible to somehow use JsonSerializer and/or JsonDeserializer together with the TypeAdapterFactory? Alternatively, is there a factory for them?

解决方案

It is possible to create a TypeAdapter that delegates one of its methods. This use case is an important part of the API, and there's a getDelegateAdapter() method for just this purpose. Pass this as the first argument to getDelegateAdapter which will return the adapter that takes precedence after the current factory.

TypeAdapterFactory immutableListFactory = new TypeAdapterFactory() {
  @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    if (!(type.getType() instanceof ParameterizedType)
        || !type.getRawType().equals(ImmutableList.class)) {
      return null;
    }

    ParameterizedType parameterizedType = (ParameterizedType) type.getType();
    TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
    TypeAdapter<?> elementAdapter = gson.getAdapter(
        TypeToken.get(parameterizedType.getActualTypeArguments()[0]));
    return new ImmutableListAdapter(delegate, elementAdapter);
  }

  class ImmutableListAdapter<E> extends TypeAdapter<ImmutableList<E>> {
    private TypeAdapter<List<E>> delegate;
    private TypeAdapter<E> element;

    ImmutableListAdapter(TypeAdapter<List<E>> delegate, TypeAdapter<E> element) {
      this.delegate = delegate;
      this.element = element;
    }

    @Override public void write(JsonWriter out, ImmutableList<E> value) throws IOException {
      delegate.write(out, value);
    }

    @Override public ImmutableList<E> read(JsonReader in) throws IOException {
      if (in.peek() == JsonToken.NULL) {
        in.nextNull();
        return null;
      }
      ImmutableList.Builder<E> builder = ImmutableList.builder();
      in.beginArray();
      while (in.hasNext()) {
        builder.add(element.read(in));
      }
      in.endArray();
      return builder.build();
    }
  }
};

You can mix and match JsonSerializer/JsonDeserializer with TypeAdapterFactory, but not directly. The simplest way is to call back into Gson to serialize child values in your class. In this example we'd change the inner loop to this:

      while (in.hasNext()) {
        builder.add(gson.<E>fromJson(in, elementType));
      }

The main difference between JsonSerializer/JsonDeserializer and TypeAdapter is how many stages it takes to go from JSON to your object model. With JsonSerializer/JsonDeserializer objects are first converted to Gson's DOM model (JsonElement etc.) and then converted into your object model. With TypeAdapter, the intermediate step is skipped.

This makes the type adapter code a little trickier to read and write, so you should prefer it only for optimized code.

这篇关于更简单的使用TypeAdapterFactory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆