簡體   English   中英

Jackson 序列化:如何忽略超類屬性

[英]Jackson serialization: how to ignore superclass properties

我想序列化一個不受我控制的 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 復制相同的解決方案。

到目前為止,我已經找到了以下可能的解決方案:

  • 使用像這樣的混合技術忽略來自超類的特定字段: 如何告訴 jackson 忽略我無法控制源代碼的屬性?

    這樣做的問題是,如果基類發生變化(例如,其中出現了一個新的 getAnything() 方法),它可能會破壞我的實現。

  • 實現自定義序列化程序並在那里處理問題。 這對我來說似乎有點矯枉過正。

  • 順便說一下,我有一個接口,它准確地描述了我想要序列化的屬性,也許我可以混合一個 @JsonSerialize(as=IMyGenerated.class) 注釋......? 我可以將它用於我的目的嗎?

但是,從純設計的角度來看,最好是能夠告訴 jackson 我只想序列化最終類的屬性,而忽略所有繼承的屬性。 有沒有辦法做到這一點?

提前致謝。

您可以注冊一個自定義的Jackson 注釋引入器,它會忽略來自某個超類型的所有屬性。 下面是一個例子:

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

繼承的好處在於子類擴展或添加功能。 所以通常的方式是對數據進行序列化。

一種解決方法是將值對象 (VO) 或數據傳輸對象 (DTO) 與您需要序列化的字段一起使用。 腳步:

  • 使用應序列化的字段創建一個 VO 類。
  • 使用 BeanUtils.copyProperties(target VO, source data) 復制屬性
  • 序列化 VO 實例。

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

@JsonInclude(Include.NON_NULL)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM