简体   繁体   English

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

[英]Jackson serialization: how to ignore superclass properties

I want to serialize a POJO class which is not under my control, but want to avoid serializing any of the properties which are coming from the superclass, and not from the final class.我想序列化一个不受我控制的 POJO 类,但想避免序列化来自超类而不是来自最终类的任何属性。 Example:例子:

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

You can guess from the example that that this class is generated by JOOQ, and inherits from a complex base class UpdatableRecordImpl which also has some bean property-like methods, which cause problems during the serialization.从例子中可以猜到,这个类是由JOOQ生成的,继承自一个复杂的基类UpdatableRecordImpl,它也有一些类似bean属性的方法,在序列化过程中会出现问题。 Also, I have several similar classes, so it would be good to avoid duplicating the same solution for all of my generated POJOs.此外,我有几个类似的类,因此最好避免为我生成的所有 POJO 复制相同的解决方案。

I have found the following possible solutions so far:到目前为止,我已经找到了以下可能的解决方案:

  • ignore the specific fields coming from superclass using mixin technique like this: How can I tell jackson to ignore a property for which I don't have control over the source code?使用像这样的混合技术忽略来自超类的特定字段: 如何告诉 jackson 忽略我无法控制源代码的属性?

    The problem with this is that if the base class changes (eg, a new getAnything() method appears in it), it can break my implementation.这样做的问题是,如果基类发生变化(例如,其中出现了一个新的 getAnything() 方法),它可能会破坏我的实现。

  • implement a custom serializer and handle the issue there.实现自定义序列化程序并在那里处理问题。 This seems a bit overkill to me.这对我来说似乎有点矫枉过正。

  • as incidentally I have an interface which describes exactly the properties I want to serialize, maybe I can mixin a @JsonSerialize(as=IMyGenerated.class) annotation...?顺便说一下,我有一个接口,它准确地描述了我想要序列化的属性,也许我可以混合一个 @JsonSerialize(as=IMyGenerated.class) 注释......? Can I use this for my purpose?我可以将它用于我的目的吗?

But, from pure design point of view, the best would be to be able to tell jackson that I want to serialize only the final class' properties, and ignore all the inherited ones.但是,从纯设计的角度来看,最好是能够告诉 jackson 我只想序列化最终类的属性,而忽略所有继承的属性。 Is there a way to do that?有没有办法做到这一点?

Thanks in advance.提前致谢。

You can register a custom Jackson annotation intropector which would ignore all the properties that come from the certain super type.您可以注册一个自定义的Jackson 注释引入器,它会忽略来自某个超类型的所有属性。 Here is an example:下面是一个例子:

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

}

Output:输出:

{ "field2" : "b" } {“字段2”:“b”}

You can override the superclass' methods which you'd like to prevent from being output and annotate them with @JsonIgnore.您可以覆盖要防止输出的超类方法,并使用@JsonIgnore 对其进行注释。 The override shifts the control of property creation to the subclass while enabling its ability to filter it from the output.覆盖将属性创建的控制权转移到子类,同时使其能够从输出中过滤它。

For instance:例如:

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

You can use this as well instead of unnecessary overrides您也可以使用它来代替不必要的覆盖

@JsonIgnoreProperties({ "aFieldFromSuperClass"})
public class Child extends Base {
   private String id;       
   private String name; 
   private String category;
} 

The good use of inheritance is that the child classes extend or add functionality.继承的好处在于子类扩展或添加功能。 So the usual way is to serialize the data.所以通常的方式是对数据进行序列化。

A workarround would be to use a Value Object (VO) or Data Transfer Object (DTO) with the fields you need to serialize.一种解决方法是将值对象 (VO) 或数据传输对象 (DTO) 与您需要序列化的字段一起使用。 Steps:脚步:

  • Create a VO class with the fields that should be serialized.使用应序列化的字段创建一个 VO 类。
  • Use BeanUtils.copyProperties(target VO, source data) to copy the properties使用 BeanUtils.copyProperties(target VO, source data) 复制属性
  • Serialize the VO instance.序列化 VO 实例。

在您的 Base Class 中添加以下注释:

@JsonInclude(Include.NON_NULL)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM