Esse problema me deixou louco: o Spring é uma ferramenta tão potente e, no entanto, uma coisa tão simples como escrever uma String de saída como o JSON parece impossível sem hacks feios.
Minha solução (no Kotlin) que eu acho menos intrusiva e transparente é usar um conselho de controlador e verificar se a solicitação foi para um conjunto específico de pontos de extremidade (API REST normalmente, pois geralmente queremos retornar TODAS as respostas daqui como JSON e não faça especializações no front-end com base em se os dados retornados são uma sequência simples ("Não faça desserialização de JSON!") ou outra coisa ("Faça desserialização de JSON!")). O aspecto positivo disso é que o controlador permanece o mesmo e sem hacks.
O supports
método garante que todas as solicitações que foram tratadas pelo StringHttpMessageConverter
(por exemplo, o conversor que lida com a saída de todos os controladores que retornam strings simples) sejam processadas e, no beforeBodyWrite
método, controlamos em quais casos queremos interromper e converter a saída em JSON (e modifique os cabeçalhos de acordo).
@ControllerAdvice
class StringToJsonAdvice(val ob: ObjectMapper) : ResponseBodyAdvice<Any?> {
override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean =
converterType === StringHttpMessageConverter::class.java
override fun beforeBodyWrite(
body: Any?,
returnType: MethodParameter,
selectedContentType: MediaType,
selectedConverterType: Class<out HttpMessageConverter<*>>,
request: ServerHttpRequest,
response: ServerHttpResponse
): Any? {
return if (request.uri.path.contains("api")) {
response.getHeaders().contentType = MediaType.APPLICATION_JSON
ob.writeValueAsString(body)
} else body
}
}
Espero que, no futuro, recebamos uma anotação simples na qual possamos substituir o que HttpMessageConverter
deve ser usado para a saída.