杰克逊序列化:如何忽略超类属性

Fer*_*enc 28 java inheritance serialization superclass jackson

我想序列化一个不受我控制的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();
...
}
Run Code Online (Sandbox Code Playgroud)

您可以从示例中猜测此类是由JOOQ生成的,并且继承自复杂的基类UpdatableRecordImpl,该类还具有一些类似于bean属性的方法,这会在序列化期间导致问题.此外,我有几个类似的类,所以最好避免为我生成的所有POJO重复相同的解决方案.

到目前为止,我找到了以下可能的解决方案:

  • 使用mixin技术忽略来自超类的特定字段,如下所示:如何告诉jackson忽略我无法控制源代码的属性?

    这个问题是如果基类发生变化(例如,新的getAnything()方法出现在它中),它可能会破坏我的实现.

  • 实现自定义序列化程序并在那里处理问题.这对我来说似乎有点矫枉过正.

  • 顺便说一下,我有一个接口,它描述了我想要序列化的属性,也许我可以混合一个@JsonSerialize(as = IMyGenerated.class)注释......?我可以将此用于我的目的吗?

但是,从纯粹的设计角度来看,最好的方法是告诉杰克逊我只想序列化最终类的属性,并忽略所有继承的属性.有没有办法做到这一点?

提前致谢.

Ale*_*lov 20

您可以注册一个自定义的Jackson注释内部操作程序,它将忽略来自某个超类型的所有属性.这是一个例子:

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

}
Run Code Online (Sandbox Code Playgroud)

输出:

{"field2":"b"}

  • 这个解决方案对我有用.为了忽略复杂的JOOQ基类,我的```hasIgnoreMarker```实现是```return m.getDeclaringClass().getName().contains("org.jooq")|| super.hasIgnoreMarker(米)``` (3认同)

eth*_*esx 13

您可以覆盖要阻止输出的超类'方法,并使用@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();
  };
...
}
Run Code Online (Sandbox Code Playgroud)

  • 如果基类中的字段有限,则它是不错的选择。 (2认同)

Ism*_*hin 11

您也可以使用它来代替不必要的覆盖

@JsonIgnoreProperties({ "aFieldFromSuperClass"})
public class Child extends Base {
   private String id;       
   private String name; 
   private String category;
} 
Run Code Online (Sandbox Code Playgroud)