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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26945580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:55:24  来源:igfitidea点击:

Hymanson serialization: how to ignore superclass properties

javainheritanceserializationHymansonsuperclass

提问by Ferenc

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. Example:

我想序列化一个不受我控制的 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();
...
}

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. Also, I have several similar classes, so it would be good to avoid duplicating the same solution for all of my generated POJOs.

从例子中可以猜到,这个类是由JOOQ生成的,继承自一个复杂的基类UpdatableRecordImpl,该类也有一些类似bean属性的方法,在序列化过程中会出现问题。此外,我有几个类似的类,因此最好避免为我生成的所有 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 Hymanson to ignore a property for which I don't have control over the source code?

    The problem with this is that if the base class changes (e.g., a new getAnything() method appears in it), it can break my implementation.

  • 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...? Can I use this for my purpose?

  • 使用像这样的混合技术忽略来自超类的特定字段:如何告诉 Hymanson 忽略我无法控制源代码的属性?

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

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

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

But, from pure design point of view, the best would be to be able to tell Hymanson that I want to serialize only the final class' properties, and ignore all the inherited ones. Is there a way to do that?

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

Thanks in advance.

提前致谢。

采纳答案by Alexey Gavrilov

You can register a custom Hymanson annotation intropectorwhich would ignore all the properties that come from the certain super type. Here is an example:

您可以注册一个自定义的Hymanson 注释引入器,它会忽略来自某个超类型的所有属性。下面是一个例子:

public class HymansonIgnoreInherited {

    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 HymansonAnnotationIntrospector {
        @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" }

{“field2”:“b”}

回答by ethesx

You can override the superclass' methods which you'd like to prevent from being output and annotate them with @JsonIgnore. The override shifts the control of property creation to the subclass while enabling its ability to filter it from the output.

您可以覆盖要防止输出的超类方法,并使用@JsonIgnore 对其进行注释。覆盖将属性创建的控制权转移到子类,同时使其能够从输出中过滤它。

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

回答by Ismail Sahin

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

回答by jordiburgos

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. Steps:

一种解决方法是将值对象 (VO) 或数据传输对象 (DTO) 与您需要序列化的字段一起使用。脚步:

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