向 Jackson 的 ObjectMapper 添加自定义序列化器和反序列化器

有时,Spring Data REST 的 ObjectMapper(已特别配置为使用智能序列化器,能够将领域对象转换为链接并可反向还原)可能无法正确处理您的领域模型。您的数据结构方式多种多样,可能会发现自己的领域模型无法正确转换为 JSON。在这些情况下,以通用方式支持复杂的领域模型有时并不现实。有时,根据复杂程度的不同,甚至根本不可能提供一种通用的解决方案。spring-doc.cadn.net.cn

为了覆盖绝大多数使用场景,Spring Data REST 会尽力正确地渲染您的对象图。它会尝试将非托管的 Bean 作为普通 POJO 进行序列化,并在必要时为托管的 Bean 创建链接。然而,如果您的领域模型不适合直接读写纯 JSON,您可能需要使用自定义的类型映射和(反)序列化器来配置 Jackson 的 ObjectMapperspring-doc.cadn.net.cn

抽象类注册

您可能需要介入的一个关键配置点是:当您在领域模型中使用抽象类(或接口)时。默认情况下,Jackson 并不知道应该为某个接口创建哪种具体实现。请考虑以下示例:spring-doc.cadn.net.cn

@Entity
public class MyEntity {

  @OneToMany
  private List<MyInterface> interfaces;
}

在默认配置下,当你向导出器(exporter)发送 POST 请求以提交新数据时,Jackson 并不知道应该实例化哪个类。你需要通过注解告诉 Jackson,或者更清晰的方式是,通过使用 Module 注册一个类型映射。spring-doc.cadn.net.cn

在您的 Module 范围内声明的任何 ApplicationContext bean 都会被导出器自动识别,并注册到其 ObjectMapper 中。要添加这种特殊的抽象类类型映射,您可以创建一个 Module bean,并在其 setupModule 方法中添加一个合适的 TypeResolver,如下所示:spring-doc.cadn.net.cn

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

一旦你在自己的 SetupContext 中获得了 Module 对象,就可以执行各种酷炫的操作来配置 Jackson 的 JSON 映射。你可以阅读更多关于 Jackson Wiki 上 Modules 的工作原理spring-doc.cadn.net.cn

为领域类型添加自定义序列化器

如果你想以特殊方式序列化或反序列化某个领域类型,可以向 Jackson 的 ObjectMapper 注册你自己的实现。这样,Spring Data REST 导出器就能透明地正确处理这些领域对象。spring-doc.cadn.net.cn

要在您实现的 setupModule 方法中添加序列化器,可以执行如下操作:spring-doc.cadn.net.cn

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 仍能正确处理这些对象。spring-doc.cadn.net.cn