首页 > 解决方案 > 如何配置 Spring 以使用 Json4s 序列化响应主体?

问题描述

我在 Scala 项目中使用 Spring Boot,并且已经使用 Json4s 对 JSON 进行序列化和反序列化。到目前为止,我一直在编写这样的端点:

@RequestMapping(path = Array("/getSomething"), produces = Array(MediaType.APPLICATION_JSON_VALUE))
def getSomething: String = {
  // do some things
  val resultValue: ResultType = ??? // where ResultType is some case class that can be serialized with json4s
  json4s.native.Serialization.write(resultValue)
}

但是,我真的希望能够避免最后一步,同时更清楚端点的返回类型是什么。此外,我希望能够提取返回类型以生成 API 文档。所以相反,我想写这样的东西:

@RequestMapping(path = Array("/getSomething"), produces = Array(MediaType.APPLICATION_JSON_VALUE))
def getSomething: ResultType = {
  // do some things
  resultValue
}

但是,当我这样做时,结果总是只是{}. 我认为这是因为 Spring 使用的是 Jackson 而不是 Json4s,并且我没有注释用于 Jackson 的案例类。我要做的就是添加一些在每个端点上调用的拦截器,并将结果转换为 JSON 字符串。编写拦截器很容易(它只是json4s.native.Serialization.write),但是我怎样才能注册它以便让 Spring 每次都自动使用它呢?

标签: springscalajacksonjson4s

解决方案


您可以使用该json4s-jackson模块并通过创建一个 Spring Bean 来使用自定义序列化器注册您的案例类,例如:

  @Bean def json4sCustomizer: Jackson2ObjectMapperBuilderCustomizer = builder => {
    builder.serializerByType(classOf[ResultType], new JsonSerializer[ResultType] {
      val json4sSerializer = new json4s.jackson.JValueSerializer
      implicit val formats:Formats = DefaultFormats

      override def serialize(value: ResultType, gen: JsonGenerator, serializers: SerializerProvider): Unit =
        json4sSerializer.serialize(json4s.Extraction.decompose(value), gen, serializers)
    })
  }

完全替换 Jackson 将涉及HTTP 消息转换器,并且可能更方便/更不方便,具体取决于您的应用程序的其他问题

  @Bean def json4sConverter: HttpMessageConverter[AnyRef] = new AbstractJsonHttpMessageConverter {
    override def readInternal(resolvedType: Type, reader: Reader): AnyRef = ???
    override def writeInternal(value: Any, typ: Type, writer: Writer): Unit = ???
  }

推荐阅读