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

时间:2014-11-15 11:57:53

标签: java inheritance serialization jackson superclass

我想序列化一个不受我控制的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技术忽略来自超类的特定字段,如下所示:How can I tell jackson to ignore a property for which I don't have control over the source code?

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

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

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

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

提前致谢。

5 个答案:

答案 0 :(得分:18)

您可以注册一个自定义Jackson annotation intropector,它会忽略来自特定超类型的所有属性。这是一个例子:

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

}

输出:

{   &#34; FIELD2&#34; :&#34; b&#34; }

答案 1 :(得分:9)

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

答案 2 :(得分:3)

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

GroupBy.indices

答案 3 :(得分:2)

继承的良好用法是子类扩展或添加功能。所以通常的方法是序列化数据。

workarround将使用值对象(VO)或数据传输对象(DTO)以及您需要序列化的字段。步骤进行:

  • 使用应序列化的字段创建一个VO类。
  • 使用BeanUtils.copyProperties(目标VO,源数据)复制属性
  • 序列化VO实例。

答案 4 :(得分:-1)

在基类中添加以下注释:

@JsonInclude(Include.NON_NULL)