Jackson serialización: cómo ignorar las propiedades de superclase


Quiero serializar una clase POJO que no está bajo mi control, pero quiero evitar serializar cualquiera de las propiedades que vienen de la superclase, y no de la clase final. Ejemplo:

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();
...
}

Puede adivinar a partir del ejemplo que esta clase es generada por JOOQ, y hereda de una compleja clase base UpdatableRecordImpl que también tiene algunos métodos de propiedad bean, que causan problemas durante la serialización. Además, tengo varias clases similares, por lo que sería sería bueno evitar duplicar la misma solución para todos mis POJOs generados.

He encontrado las siguientes soluciones posibles hasta ahora:

  • Ignore los campos específicos que provienen de superclass usando la técnica mixin de esta manera: ¿Cómo puedo decirle a Jackson que ignore una propiedad para la que no tengo control sobre el código fuente?

    El problema con esto es que si la clase base cambia (por ejemplo, aparece un nuevo método getAnything ()), puede romper mi aplicación.

  • Implementar un serializador personalizado y manejar el problema allí. Esto me parece un poco exagerado.

  • Como por cierto tengo una interfaz que describe exactamente las propiedades que quiero serializar, tal vez puedo mixin a @JsonSerialize(as=IMyGenerated.class) anotación...? Puedo usar esto para mi propósito?

Pero, desde el punto de vista del diseño puro, lo mejor sería poder decirle a Jackson que quiero serializar solo el final propiedades de la clase, e ignora todas las heredadas. ¿Hay alguna manera de hacer eso?

Gracias de antemano.

Author: Community, 2014-11-15

3 answers

Puede registrar un intropector personalizado de anotación Jackson que ignoraría todas las propiedades que provienen del tipo super determinado. He aquí un ejemplo:

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));
    }

}

Salida:

{ "campo2" : "b" }

 17
Author: Alexey Gavrilov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-15 20:48:11

Puede anular los métodos de la superclase que desea evitar que se generen y anotarlos con @JsonIgnore. La anulación desplaza el control de la creación de propiedades a la subclase mientras habilita su capacidad para filtrarla de la salida.

Por ejemplo:

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();
  };
...
}
 6
Author: ethesx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-15 11:59:08

El buen uso de la herencia es que las clases hijo amplían o añaden funcionalidad. Así que la forma habitual es serializar los datos.

Un workarround sería usar un Objeto de Valor (VO) o un Objeto de Transferencia de Datos (DTO) con los campos que necesita serializar. Pasos:

  • Cree una clase VO con los campos que deben ser serializados.
  • Utilice BeanUtils.copyProperties (VO de destino, datos de origen) para copiar las propiedades
  • Serializar la instancia VO.
 2
Author: jordiburgos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-15 12:12:03