Jackson serialization: how to ignore superclass properties

26,768

Solution 1

You can register a custom Jackson annotation intropector which would ignore all the properties that come from the certain super type. Here is an example:

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

}

Output:

{ "field2" : "b" }

Solution 2

You can override the superclass' methods which you'd like to prevent from being output and annotate them with @JsonIgnore. The override shifts the control of property creation to the subclass while enabling its ability to filter it from the output.

For instance:

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

Solution 3

You can use this as well instead of unnecessary overrides

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

Solution 4

The good use of inheritance is that the child classes extend or add functionality. So the usual way is to serialize the data.

A workarround would be to use a Value Object (VO) or Data Transfer Object (DTO) with the fields you need to serialize. Steps:

  • Create a VO class with the fields that should be serialized.
  • Use BeanUtils.copyProperties(target VO, source data) to copy the properties
  • Serialize the VO instance.
Share:
26,768
Ferenc
Author by

Ferenc

Updated on November 26, 2020

Comments

  • Ferenc
    Ferenc over 3 years

    I want to serialize a POJO class which is not under my control, but want to avoid serializing any of the properties which are coming from the superclass, and not from the final class. Example:

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

    You can guess from the example that that this class is generated by JOOQ, and inherits from a complex base class UpdatableRecordImpl which also has some bean property-like methods, which cause problems during the serialization. Also, I have several similar classes, so it would be good to avoid duplicating the same solution for all of my generated POJOs.

    I have found the following possible solutions so far:

    • ignore the specific fields coming from superclass using mixin technique like this: How can I tell jackson to ignore a property for which I don't have control over the source code?

      The problem with this is that if the base class changes (e.g., a new getAnything() method appears in it), it can break my implementation.

    • implement a custom serializer and handle the issue there. This seems a bit overkill to me.

    • as incidentally I have an interface which describes exactly the properties I want to serialize, maybe I can mixin a @JsonSerialize(as=IMyGenerated.class) annotation...? Can I use this for my purpose?

    But, from pure design point of view, the best would be to be able to tell jackson that I want to serialize only the final class' properties, and ignore all the inherited ones. Is there a way to do that?

    Thanks in advance.