Ten problem doprowadził mnie do szaleństwa: Spring jest tak potężnym narzędziem, a jednak tak prosta rzecz, jak napisanie wyjściowego ciągu znaków jako JSON, wydaje się niemożliwa bez brzydkich hacków.
Moim rozwiązaniem (w Kotlinie), które uważam za najmniej inwazyjne i najbardziej przejrzyste, jest skorzystanie z porady kontrolera i sprawdzenie, czy żądanie trafiło do określonego zestawu punktów końcowych (zazwyczaj REST API, ponieważ najczęściej chcemy zwrócić WSZYSTKIE odpowiedzi stąd jako JSON i nie twórz specjalizacji w interfejsie użytkownika na podstawie tego, czy zwracane dane są zwykłym ciągiem znaków („Nie wykonuj deserializacji JSON!”), czy czymś innym („Wykonaj deserializację JSON!”)). Pozytywnym aspektem jest to, że kontroler pozostaje ten sam i bez hacków.
supports
Metoda zapewnia, że wszystkie wnioski, które były obsługiwane przez StringHttpMessageConverter
(np konwerter, który obsługuje wyjście wszystkich sterowników, które zwracają zwykłe struny) są przetwarzane oraz w beforeBodyWrite
metodzie możemy kontrolować, w jakich przypadkach chcemy przerwać i konwertować dane wyjściowe do JSON (i odpowiednio zmodyfikuj nagłówki).
@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
}
}
Mam nadzieję, że w przyszłości otrzymamy prostą adnotację, w której będziemy mogli nadpisać, która HttpMessageConverter
powinna być użyta do wyniku.