Во-первых, , чтобы Gson мог сериализовать (или десериализовать) группу объектов разных типов, имеющих одинаковый тип адаптации, наилучшим способом избежать регистрации большого количества адаптеров или изменения объявлений классов - это воспользоваться преимуществами TypeAdapterFactory
.
Он не привязан ни к какому Type
или Class
, но решает для каждого типа, который TypeAdapter
будет возвращаться, когда Gson сталкивается с каким-либо объектом для сериализации (или десериализации). Использование TypeAdaterFactory
освобождает код от регистрации лотов TypeAdapter
s.
Во-вторых и, естественно, чтобы избежать создания многих TypeAdapter
s, решение состоит в том, чтобы по возможности создать общий тип TypeAdapter
.
Начиная с обычного TypeAdapter
в вопросах, это может выглядеть так:
@RequiredArgsConstructor
private class GenericTypeAdapter<T> extends TypeAdapter<T> {
// typeToken is needed when deserializing
private final TypeToken<T> typeToken;
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
@Override
public void write(JsonWriter out, T value) throws IOException {
// Altering could be done with some low level string manipulation
// but JsonObject makes altering object more safe.
// Feel free to comment for better way to instantiate it,
// this is just for an example.
JsonObject jsonObject = gson.fromJson(gson.toJson(value)
,JsonElement.class).getAsJsonObject();
// alter jsonObject in any way needed,
// here is only added version information
jsonObject.addProperty("version", 1);
out.jsonValue(gson.toJson(jsonObject));
}
@Override
public T read(JsonReader in) throws IOException {
// maybe needless to mention but mention still:
// here it is possible to init object in a way
// that provided JSON solely does not make possible
return gson.fromJson(in, typeToken.getType());
}
}
Тогда TypeAdapterFactory
. Это довольно просто, но обратите внимание на комментарии в примере кода. Как упоминалось ранее, TypeAdapterFactory
отвечает за возвращение правильных TypeAdapter
для объекта. Хотя он предназначен для применения к связке типов, он не должен применяться к всем типам. Самый простой TypeAdapterFactory
:
public class GenericTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
// here should be checked if the passed type needs any custom
// adapter and if it needs then decide which adapter to return
// or in case of no customization needed return null for default
// adapter.
// decision can be made for example by
// * type itself
// * package name
// * if type implements / extends some super type
return new GenericTypeAdapter<>(type);
}
}
Использование тогда будет просто:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new GenericTypeAdapterFactory())
.setPrettyPrinting()
.create()
Примечание : я подготовил этот ответ первоначально к к этому вопросу , но, поскольку позже он, по-видимому, основывался на котлине (?), Я чувствовал себя лучше для создания более общих вопросов и ответов, касающихся Java.