【问题标题】:How can I configure Spring to use Json4s to serialize response bodies?如何配置 Spring 以使用 Json4s 序列化响应主体?
【发布时间】:2020-10-21 19:40:06
【问题描述】:

我在 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 每次都自动使用它?

【问题讨论】:

标签: spring scala jackson json4s


【解决方案1】:

您可以使用 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 Message Converters 并且可能更方便/更不方便,具体取决于您的应用程序的其他问题

  @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 = ???
  }

【讨论】:

  • 感谢您的信息。您能否提供有关使用消息转换器的更多详细信息?我看到了AbstractJsonHttpMessageConverter,但我不确定如何创建和注册它以使其可用于每种返回类型(AnyRef)。我觉得消息转换器的方式更适用于我的用例,因为我想对每个端点都使用它。
  • 序列化器方法适用于使用注册类型的每个端点。如果你有多个案例类,你可以用一个共同的特征注册它,甚至是scala.Product
猜你喜欢
  • 1970-01-01
  • 2021-06-16
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
  • 1970-01-01
  • 2020-02-04
  • 2015-06-07
相关资源
最近更新 更多