AFAIK可以通过TypeAdapterFactory进行最灵活的gson定制,但是它可能变得不必要地复杂。它迫使我为每个处理的类编写readwrite,而有时确实只需要一种方法。此外,有时候JsonSerializer和/或JsonDeserializer容易编写得多,例如like here。这使我想到了以下问题:

  • 是否可以编写简单地委派其方法之一的TypeAdapter(例如,将ImmutableList写入到List写入)?
  • 是否可以将JsonSerializer和/或JsonDeserializerTypeAdapterFactory一起使用?另外,他们有工厂吗?
  • 最佳答案

    可以创建代表其方法之一的TypeAdapter。这个用例是API的重要组成部分,并且有一个getDelegateAdapter()方法用于此目的。将this作为第一个参数传递给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)) {
          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();
        }
      }
    };
    

    您可以将JsonSerializer/JsonDeserializerTypeAdapterFactory混合并匹配,但不能直接匹配。最简单的方法是回调Gson来序列化类中的子值。在此示例中,我们将内部循环更改为:
          while (in.hasNext()) {
            builder.add(gson.<E>fromJson(in, elementType));
          }
    
    JsonSerializer/JsonDeserializerTypeAdapter之间的主要区别是从JSON到您的对象模型需要多少阶段。使用JsonSerializer/JsonDeserializer,对象首先被转换为Gson的DOM模型(JsonElement等),然后被转换为您的对象模型。使用TypeAdapter,将跳过中间步骤。

    这使类型适配器代码的读写有些棘手,因此您仅应将其用于优化代码。

    07-26 08:02