Проще использовать TypeAdapterFactory
AFAIK самая гибкая настройка gson возможна через TypeAdapterFactory
, однако это может стать ненужно сложным. Это заставляет меня писать для каждого обработанного класса both read
и write
, хотя иногда действительно нужен только один метод. Более того, иногда JsonSerializer
и/или JsonDeserializer
было намного проще писать, например как тут. Это подводит меня к следующим вопросам:--14-->
- можно писать
TypeAdapter
который просто делегирует одного из своих методов (например, записьImmutableList
в видеList
)? - можно ли как-то использовать
JsonSerializer
и/илиJsonDeserializer
вместе сTypeAdapterFactory
? В качестве альтернативы, есть ли для них фабрика?
1 ответов
можно создать 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
/JsonDeserializer
С TypeAdapterFactory
, но не напрямую. Самый простой способ-перезвонить в Gson для сериализации дочерние ценности в вашем классе. В этом примере мы изменим внутренний цикл на это:
while (in.hasNext()) {
builder.add(gson.<E>fromJson(in, elementType));
}
основное различие между JsonSerializer
/JsonDeserializer
и TypeAdapter
сколько этапов требуется, чтобы перейти от JSON к вашей объектной модели. С JsonSerializer
/JsonDeserializer
объекты сначала преобразуются в модель DOM Gson (JsonElement
etc.), а затем преобразуется в объектную модель. С TypeAdapter
промежуточный шаг пропускается.
это делает код адаптера типа немного сложнее читать и пишите, поэтому вы должны предпочесть его только для оптимизированного кода.