Я думаю, что идея InstanceCreator
обманчиво противоречит принципу работы ReflectiveTypeAdapterFactory
:
- первый имеет дело с классами, которые фактически являются пакетами данных, а не интерфейсами (и об этом говорит пример в интерфейсе JavaDo c);
- , в то время как последний, согласно исходному коду, разрешает class связанные поля (не интерфейсы, которые не объявляют поля) заранее применение стратегий переопределения для
@SerializedName
, что повышает сложность.
Звучит до некоторой степени нелогично, но я не думаю, что это проблема дизайна, скорее ловушка , Здесь вы можете создать адаптер нестандартного типа, который заимствует адаптер подтипа для своего супертипа:
public static <T1, T2 extends T1> TypeAdapterFactory bind(final TypeToken<T1> superTypeToken, final TypeToken<T2> subTypeToken) {
return new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
if ( !typeToken.equals(superTypeToken) ) {
return null;
}
@SuppressWarnings("unchecked")
final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) gson.getDelegateAdapter(this, subTypeToken);
return typeAdapter;
}
};
}
, а затем зарегистрировать его в сборщике Gson:
private static final TypeToken<Foo> fooTypeToken = new TypeToken<Foo>() {};
private static final TypeToken<FooImpl> fooImplTypeToken = new TypeToken<FooImpl>() {};
private static final Gson gson = new GsonBuilder()
.serializeNulls()
.registerTypeAdapterFactory(bind(fooTypeToken, fooImplTypeToken))
.create();
Это должно быть идеальным вариантом для вас.
(Пример, предоставленный Dici, является еще одним примером использования: это адаптер типа polymorphi c, который десериализует объект из поддерева JSON на основе JSON свойство, которое определяет тип для создания экземпляра. С другой стороны, метод bind
, описанный выше, можно рассматривать как специальную специализацию "без типа" для RuntimeTypeAdapterFactory
.)