Страницы

Поиск по вопросам

пятница, 1 марта 2019 г.

Сериализация в JSON как объект конкретного класса

Есть у меня объект такого класса
class A { List items; }
Я хочу его сериализовать в 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; }
Все. теперь при сериализации поля 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; } }

Комментариев нет:

Отправить комментарий