更简单地使用TypeAdapterFactory

AFAIK可以通过TypeAdapterFactory进行最灵活的gson定制,但是它可能会变得不必要地复杂化。 它迫使我为每个被处理的类write ,而有时只需要一个方法。 此外,有时候JsonSerializer和/或JsonDeserializer更容易编写,例如像这里一样 。 这引出了我这些问题:

  • 是否可以编写一个简单地委托其中一个方法的TypeAdapter (例如将ImmutableList写入List写入)?
  • 有可能以某种方式将JsonSerializer和/或JsonDeserializerJsonDeserializer一起使用吗? 或者,他们有工厂吗?

可以创建一个委托其方法之一的TypeAdapter 。 这个用例是API的一个重要部分,并且有一个getDelegateAdapter()方法就是为了这个目的。 this作为getDelegateAdapter的第一个参数传递,该参数将返回在当前工厂之后优先的适配器。

 TypeAdapterFactory immutableListFactory = new TypeAdapterFactory() { @Override public  TypeAdapter create(Gson gson, TypeToken type) { if (!(type.getType() instanceof ParameterizedType) || !type.getRawType().equals(ImmutableList.class)) { return null; } ParameterizedType parameterizedType = (ParameterizedType) type.getType(); TypeAdapter delegate = gson.getDelegateAdapter(this, type); TypeAdapter elementAdapter = gson.getAdapter( TypeToken.get(parameterizedType.getActualTypeArguments()[0])); return new ImmutableListAdapter(delegate, elementAdapter); } class ImmutableListAdapter extends TypeAdapter> { private TypeAdapter> delegate; private TypeAdapter element; ImmutableListAdapter(TypeAdapter> delegate, TypeAdapter element) { this.delegate = delegate; this.element = element; } @Override public void write(JsonWriter out, ImmutableList value) throws IOException { delegate.write(out, value); } @Override public ImmutableList read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } ImmutableList.Builder 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.fromJson(in, elementType)); } 

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

这使得类型适配器代码的读写变得有点棘手,因此您应该优先考虑优化代码。