Java Jackson序列化:如何忽略超类属性
我想序列化一个不在我控制之下的POJO类,但要避免序列化来自超类而不是最终类的任何属性。例如:Java Jackson序列化:如何忽略超类属性,java,inheritance,serialization,jackson,superclass,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 class MyGeneratedRecord extends org.jooq.impl.UpdatableRecordImpl<...>,
example.generated.tables.interfaces.IMyGenerated {
public void setField1(...);
public Integer getField1();
public void setField2(...);
public Integer getField2();
...
}
公共类MyGeneratedRecord扩展org.jooq.impl.UpdateableRecordImpl,
example.generated.tables.interfaces.IMyGenerated{
公共无效设置字段1(…);
公共整数getField1();
公共无效设置字段2(…);
公共整数getField2();
...
}
您可以从示例中猜测,这个类是由JOOQ生成的,并且继承自一个复杂的基类updateablerecordimpl,该基类还具有一些类似bean属性的方法,这些方法在序列化过程中会导致问题。此外,我有几个类似的类,因此最好避免对所有生成的POJO重复相同的解决方案
到目前为止,我已经找到了以下可能的解决方案:
- 使用mixin技术忽略来自超类的特定字段,如下所示: 这样做的问题是,如果基类发生更改(例如,其中出现一个新的getAnything()方法),它可能会破坏我的实现
- 实现一个自定义序列化程序并在那里处理问题。这对我来说似乎有点过分了
- 顺便说一句,我有一个接口,它精确地描述了我想要序列化的属性,也许我可以混合一个@JsonSerialize(as=IMyGenerated.class)注释。。。?我能用这个吗
提前感谢。继承的良好用途是子类扩展或添加功能。所以通常的方法是序列化数据 一个解决方案是使用值对象(VO)或数据传输对象(DTO)和需要序列化的字段。步骤:
- 使用应序列化的字段创建VO类
- 使用BeanUtils.copyProperties(目标VO,源数据)复制属性
- 序列化VO实例
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));
}
}
输出:
{
“字段2”:“b”
}您可以覆盖要防止输出的超类方法,并使用@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();
};
...
}
您也可以使用它,而不是不必要的覆盖
@JsonIgnoreProperties({ "aFieldFromSuperClass"})
public class Child extends Base {
private String id;
private String name;
private String category;
}
在基类中添加以下注释:
@JsonInclude(Include.NON_NULL)
在这种情况下,这将是一个纯粹的复制粘贴。使用生成的类的全部目的是避免模式信息(字段、类型等)的重复。理想情况下,一个字段的名称应该只键入一次——在我的SQL模式中(或者在ORM的情况下,在手写POJO中)。到目前为止,这在我的设计中或多或少是正确的,我不想打破这一点。否则,您需要重新定义子类上的字段并将其标记为“不可序列化”。@ference:您可以让jOOQ为您生成所有这些POJO/VOs/DTO:是的,这是另一种可能的解决方案——我已经使用了POJO,因此是一个简单的.into(MyGenerated.class)在select方法上也可以这样做。非常感谢。这个解决方案对我有效。太忽略复杂的JOOQ基类了,我的
hasIgnoreMarker
实现是返回m.getDeclaringClass().getName().contains(“org.JOOQ”)| | super.hasIgnoreMarker(m)
要添加到@AbhishekChatterjee的点上,jackson使用对象中的getter来确定要显示什么,因此只需要重写getter。