Подтвердить что ты не робот

Сериализация Джексона: как игнорировать свойства суперкласса

Я хочу сериализовать класс POJO, который не под моим контролем, но хочу избежать сериализации любых свойств, которые поступают из суперкласса, а не из последнего класса. Пример:

public class MyGeneratedRecord extends org.jooq.impl.UpdatableRecordImpl<...>,
    example.generated.tables.interfaces.IMyGenerated {
  public void setField1(...);
  public Integer getField1();

  public void setField2(...);
  public Integer getField2();
...
}

Вы можете догадаться из примера, что этот класс сгенерирован JOOQ и наследуется от сложного базового класса UpdatableRecordImpl, который также имеет некоторые bean свойства-подобные методы, которые вызывают проблемы во время сериализации. Кроме того, у меня есть несколько подобных классов, поэтому было бы неплохо избежать дублирования одного и того же решения для всех моих созданных POJO.

Я нашел следующие возможные решения:

  • игнорировать конкретные поля, поступающие из суперкласса, используя метод mixin следующим образом: Как я могу сказать jackson игнорировать свойство, для которого у меня нет контроля над исходным кодом?

    Проблема заключается в том, что при изменении базового класса (например, в нем появляется новый метод getAnything()), он может нарушить мою реализацию.

  • реализовать собственный сериализатор и обработать проблему там. Мне это кажется немного лишним.

  • поскольку, кстати, у меня есть интерфейс, который точно описывает свойства, которые я хочу сериализовать, возможно, я могу микшировать аннотацию @JsonSerialize (as = IMyGenerated.class)...? Могу ли я использовать это для своей цели?

Но, с чистой точки зрения дизайна, лучше всего было бы сказать Джексону, что я хочу сериализовать только свойства последнего класса и игнорировать все унаследованные. Есть ли способ сделать это?

Спасибо заранее.

4b9b3361

Ответ 1

Вы можете зарегистрировать пользовательский интродуктор аннотации Джексона, который будет игнорировать все свойства, которые исходят от определенного супер-типа. Вот пример:

public class JacksonIgnoreInherited {

    public static class Base {
        public final String field1;

        public Base(final String field1) {
            this.field1 = field1;
        }
    }

    public static class Bean extends Base {
        public final String field2;

        public Bean(final String field1, final String field2) {
            super(field1);
            this.field2 = field2;
        }
    }

    private static class IgnoreInheritedIntrospector extends JacksonAnnotationIntrospector {
        @Override
        public boolean hasIgnoreMarker(final AnnotatedMember m) {
            return m.getDeclaringClass() == Base.class || super.hasIgnoreMarker(m);
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new IgnoreInheritedIntrospector());
        final Bean bean = new Bean("a", "b");
        System.out.println(mapper
                        .writerWithDefaultPrettyPrinter()
                        .writeValueAsString(bean));
    }

}

Вывод:

{ "field2": "b" }

Ответ 2

Вы можете переопределить методы суперкласса, которые вы хотите запретить выводить, и аннотировать их с помощью @JsonIgnore. Переопределение сдвигает управление созданием свойства в подкласс, позволяя его возможность отфильтровывать его с выхода.

Например:

public class SomeClass {
  public void setField1(...);
  public Integer getField1();

  public void setField2(...);
  public Integer getField2();

  @Override
  @JsonIgnore
  public String superClassField1(...){
      return super.superClassField1();
  };

  @Override
  @JsonIgnore
  public String superClassField2(...){
      return super.superClassField2();
  };
...
}

Ответ 3

Хорошим использованием наследования является то, что дочерние классы расширяют или добавляют функциональность. Таким образом, обычным способом является сериализация данных.

Вокруг работы будет использовать объект Value (VO) или объект передачи данных (DTO) с полями, которые необходимо выполнить для сериализации. Шаги:

  • Создайте класс VO с полями, которые должны быть сериализованы.
  • Используйте BeanUtils.copyProperties(целевые VO, исходные данные), чтобы скопировать свойства.
  • Сериализовать экземпляр VO.

Ответ 4

Вы также можете использовать это вместо бесполезных переопределений

@JsonIgnoreProperties({ "aFieldFromSuperClass"})
public class Child extends Base {
   private String id;       
   private String name; 
   private String category;
}