Есть у меня объект такого класса
class A {
List
Я хочу его сериализовать в JSON. Пишу
A obj;
........
gson.toJson(obj);
Проблема: в items могут хранится как объекты BaseClass, так и его наследников. И Gson сериализует все поля этих объектов.
Вопрос: нельзя ли как-то указать Gson сериализовать только поля, относящиеся к BaseClass и его предкам. А поля наследников не трогать?
P.S. Наследники участвуют в сериализации других классов
Ответ
Update Или еще более простой вариант.
Реализуем сериализатор для любого List
public class GenericListSerializer implements JsonSerializer {
@Override
public JsonElement serialize(List src, Type type, JsonSerializationContext context) {
JsonArray res = new JsonArray();
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType)type;
Type[] args = paramType.getActualTypeArguments();
type = args[0];
}
for (Object item : src) {
JsonObject currentItem = (JsonObject)context.serialize(item, type);
res.add(currentItem);
}
return res;
}
}
А теперь помечаем поля специальной аннотацией
class A {
@JsonAdapter(GenericListSerializer.class)
List
Все. теперь при сериализации поля items будет вызываться сериализатор GenericListSerializer
Old version
Благодаря пинку @Drakonoved получился такой адаптер
public class CustomSerializer implements JsonSerializer {
@Override
public JsonElement serialize(A src, Type type, JsonSerializationContext context) {
// Сериализуем поля родителя без изменений
JsonObject res = (JsonObject)context.serialize(src, src.getClass().getSuperclass());
// Получаем свои поля
Field[] flds = src.getClass().getDeclaredFields();
for (Field fld : flds) {
Type fldType = fld.getGenericType();
JsonElement jField;
Object fieldVal;
try {
// Получаем значение поля
fieldVal = fld.get(src);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
// Если тип поля List и его наследники и это generic-тип
if (fld.getType().isAssignableFrom(List.class) && fldType instanceof ParameterizedType) {
// Получаем конкретные типы, которые были указаны в объявлении List<>
ParameterizedType paramType = (ParameterizedType)fldType;
Type[] args = paramType.getActualTypeArguments();
// формируем массив
JsonArray jsonArray = new JsonArray();
for (Object item : (List)fieldVal) {
// сериализуем элемент списка, как тип, который был указан при объявлении
JsonObject currentItem = (JsonObject)context.serialize(item, args[0]);
jsonArray.add(currentItem);
}
jField = jsonArray;
}
else {
// Если у нас не список, то вызываем умолчательный сериализатор
jField = context.serialize(fieldVal);
}
res.add(fld.getName(), jField);
}
return res;
}
}
Комментариев нет:
Отправить комментарий