Эта проблема привела меня в бешенство: Spring - такой мощный инструмент, и все же такая простая вещь, как написание выходной строки в виде JSON, кажется невозможной без уродливых хаков.
Мое решение (в Kotlin), которое я считаю наименее навязчивым и наиболее прозрачным, состоит в том, чтобы использовать совет контроллера и проверить, был ли запрос направлен на определенный набор конечных точек (обычно REST API), поскольку мы чаще всего хотим возвращать ВСЕ ответы отсюда в виде JSON. и не создавать специализаций во внешнем интерфейсе, основываясь на том, являются ли возвращаемые данные простой строкой («Не выполнять десериализацию JSON!») или чем-то еще («Делать десериализацию JSON!»)). Положительным моментом этого является то, что контроллер остается прежним и без взломов.
supports
Метод гарантирует , что все запросы , которые были обработаны с помощью StringHttpMessageConverter
(например , преобразователя , который обрабатывает выходные всех контроллеров , которые возвращают простые строки) обрабатываются и в beforeBodyWrite
методе, мы контролируем , в каких случаях мы хотим прервать и преобразовать вывод в формат JSON (и измените заголовки соответственно).
@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
}
}
Я надеюсь, что в будущем мы получим простую аннотацию, в которой мы можем переопределить, которую HttpMessageConverter
следует использовать для вывода.