將自定義序列化器和反序列化器新增到 Jackson 的 ObjectMapper

有時,Spring Data REST 的 ObjectMapper(已專門配置為使用智慧序列化器,這些序列化器可以將領域物件轉換為連結,然後再轉換回來)的行為可能無法正確處理您的領域模型。您可以採用多種方式組織資料,這可能導致您自己的領域模型無法正確轉換為 JSON。在這些情況下,以通用方式支援複雜的領域模型有時也不切實際。有時,取決於複雜程度,甚至無法提供通用的解決方案。

為了適應絕大多數用例,Spring Data REST 嘗試正確渲染您的物件圖。它嘗試將非受管 bean 序列化為普通 POJO,並在必要時嘗試建立指向受管 bean 的連結。但是,如果您的領域模型不容易用於讀取或寫入純 JSON,您可能希望使用自己的自定義型別對映和(反)序列化器來配置 Jackson 的 ObjectMapper

抽象類註冊

您可能需要關注的一個關鍵配置點是當您在領域模型中使用抽象類(或介面)時。預設情況下,Jackson 不知道為介面建立什麼實現。考慮以下示例

@Entity
public class MyEntity {

  @OneToMany
  private List<MyInterface> interfaces;
}

在預設配置下,當向 exporter POST 新資料時,Jackson 不知道要例項化哪個類。您需要透過註解或者更簡潔的方式,即使用 Module 註冊型別對映來告知 Jackson。

在您的 ApplicationContext 範圍內宣告的任何 Module bean 都將被 exporter 獲取並註冊到其 ObjectMapper 中。要新增這種特殊的抽象類型別對映,您可以建立一個 Module bean,並在 setupModule 方法中新增一個適當的 TypeResolver,如下所示

public class MyCustomModule extends SimpleModule {

  private MyCustomModule() {
    super("MyCustomModule", new Version(1, 0, 0, "SNAPSHOT"));
  }

  @Override
  public void setupModule(SetupContext context) {
    context.addAbstractTypeResolver(
      new SimpleAbstractTypeResolver().addMapping(MyInterface.class,
        MyInterfaceImpl.class));
  }
}

一旦您在 Module 中訪問了 SetupContext 物件,您就可以進行各種有趣的操作來配置 Jackson 的 JSON 對映。您可以在 Jackson 的 wiki 上閱讀更多關於 Modules 的工作原理

為領域型別新增自定義序列化器

如果您想以特殊方式序列化或反序列化領域型別,您可以將自己的實現註冊到 Jackson 的 ObjectMapper 中。然後 Spring Data REST exporter 將透明地正確處理這些領域物件。

要在 setupModule 方法實現中新增序列化器,您可以執行如下操作

public class MyCustomModule extends SimpleModule {

  …

  @Override
  public void setupModule(SetupContext context) {

    SimpleSerializers serializers = new SimpleSerializers();
    SimpleDeserializers deserializers = new SimpleDeserializers();

    serializers.addSerializer(MyEntity.class, new MyEntitySerializer());
    deserializers.addDeserializer(MyEntity.class, new MyEntityDeserializer());

    context.addSerializers(serializers);
    context.addDeserializers(deserializers);
  }
}

藉助前面示例中所示的自定義模組,當您的領域物件對於 Spring Data REST 嘗試涵蓋的 80% 通用用例來說過於複雜時,Spring Data REST 可以正確處理它們。