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

我想序列化一个不在我的控制之下的 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)注释...?我可以将其用于我的目的吗?

但是,从纯粹的设计角度来看,最好的办法是能够告诉 jackson,我只想序列化最终类的属性,而忽略所有继承的属性。有没有办法做到这一点?

提前致谢。


答案 1

您可以注册一个自定义 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));
    }

}

输出:

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