Jackson の ObjectMapper へのカスタムシリアライザーとデシリアライザーの追加

場合によっては、Spring Data REST ObjectMapper (ドメインオブジェクトをリンクに変換して元に戻すことができるインテリジェントシリアライザーを使用するように特別に構成されている) の動作が、ドメインモデルを正しく処理しない場合があります。独自のドメインモデルが JSON に正しく変換されないことがわかるほど多くのメソッドでデータを構造化できます。また、これらの場合、複雑なドメインモデルを一般的なメソッドでサポートすることが現実的でない場合もあります。複雑さによっては、一般的なソリューションを提供することさえ不可能な場合があります。

ユースケースの最大の割合に対応するために、Spring Data REST はオブジェクトグラフを正しくレンダリングしようとします。アンマネージド Bean を通常の POJO として直列化しようとし、必要に応じてマネージド Bean へのリンクを作成しようとします。ただし、ドメインモデルがプレーン JSON の読み取りまたは書き込みに適していない場合は、独自のカスタム型 マッピングと (デ) シリアライザーを使用して Jackson の ObjectMapper を構成することをお勧めします。

抽象クラス登録

フックする必要があるかもしれない重要な構成ポイントの 1 つは、ドメインモデルで抽象クラス(またはインターフェース)を使用する場合です。Jackson は、デフォルトでは、インターフェース用に作成する実装を認識していません。次の例を考えてみましょう。

@Entity
public class MyEntity {

  @OneToMany
  private List<MyInterface> interfaces;
}

デフォルトの構成では、Jackson は、新しいデータをエクスポーターに POST するときにインスタンス化するクラスを認識していません。アノテーションを介して、またはより明確に、モジュール (英語) を使用して型マッピングを登録することにより、Jackson に通知する必要があります。

ApplicationContext のスコープ内で宣言された Module Bean は、エクスポーターによって取得され、その 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 オブジェクトにアクセスできるようになると、Jackon の JSON マッピングを構成するためにあらゆる種類の優れた処理を実行できます。モジュールは Jackson の wiki で動作します (英語) の詳細についてはこちらを参照してください。

ドメイン型のカスタムシリアライザーの追加

特別なメソッドでドメイン型をシリアライズまたはデシリアライズしたい場合は、独自の実装を Jackson の ObjectMapper に登録できます。その後、Spring Data REST エクスポーターはそれらのドメインオブジェクトを透過的に正しく処理します。

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 は、Spring Data REST がカバーしようとする 80% の一般的なユースケースに対して複雑すぎる場合に、ドメインオブジェクトを正しく処理します。