问题描述
AFAIK可以通过 TypeAdapterFactory
实现最灵活的gson定制,但它可能会变得不必要的复杂。它迫使我为每个处理过的类写入 read
和 write
,但有时候只需要一种方法。此外,有时 JsonSerializer
和/或 JsonDeserializer
更容易编写,例如。这导致我的这些问题:- 是否可以写一个
TypeAdapter
which只需将其中一个方法委托给List
)
- 是否有可能以某种方式将
JsonSerializer
和/或JsonDeserializer
与TypeAdapterFactory
?或者,他们是否有工厂?
可以创建一个 TypeAdapter
,它委托它的一个方法。此用例是API的重要组成部分,并且有一个方法。通过这个
作为 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 ofImmutableList
to writing ofList
)? - Is it possible to somehow use
JsonSerializer
and/orJsonDeserializer
together with theTypeAdapterFactory
? 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!