Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson序列化:如何忽略超类属性_Java_Inheritance_Serialization_Jackson_Superclass - Fatal编程技术网

Java Jackson序列化:如何忽略超类属性

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

我想序列化一个不在我控制之下的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();
...
}
公共类MyGeneratedRecord扩展org.jooq.impl.UpdateableRecordImpl,
example.generated.tables.interfaces.IMyGenerated{
公共无效设置字段1(…);
公共整数getField1();
公共无效设置字段2(…);
公共整数getField2();
...
}
您可以从示例中猜测,这个类是由JOOQ生成的,并且继承自一个复杂的基类updateablerecordimpl,该基类还具有一些类似bean属性的方法,这些方法在序列化过程中会导致问题。此外,我有几个类似的类,因此最好避免对所有生成的POJO重复相同的解决方案

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

  • 使用mixin技术忽略来自超类的特定字段,如下所示:

    这样做的问题是,如果基类发生更改(例如,其中出现一个新的getAnything()方法),它可能会破坏我的实现

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

  • 顺便说一句,我有一个接口,它精确地描述了我想要序列化的属性,也许我可以混合一个@JsonSerialize(as=IMyGenerated.class)注释。。。?我能用这个吗

但是,从纯设计的角度来看,最好能够告诉jackson我只想序列化最后一个类的属性,而忽略所有继承的属性。有办法吗


提前感谢。

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

一个解决方案是使用值对象(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。