String response is not returned with a valid JSON format [SWS-1062]
Matias Canessa opened SWS-1062 and commented
Hello,
I upgraded to the last Spring version and found a problem. We have some request mappings that return a String or a ResponseEntity<String> and I found out that when returning this kind of response as a Content-type:'application/json' it doesn't return a valid Json format since it returns a literal without being wrapped in quotes.
In order to replicate this error, the request must come with the header accept:'application/json'
This results in a response with the header saying 'application/json' without it being a valid Json, causing problems with integrations with other services that expect a valid Json.
Debugging the code we found that the class AbstractMessageConverterMethodProcessor iterates over a list of converters which has this order:
[org.springframework.http.converter.ByteArrayHttpMessageConverter, org.springframework.http.converter.StringHttpMessageConverter, org.springframework.http.converter.StringHttpMessageConverter, org.springframework.http.converter.ResourceHttpMessageConverter , org.springframework.http.converter.ResourceRegionHttpMessageConverter, org.springframework.http.converter.xml.SourceHttpMessageConverter, org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter, org.springframework.http.converter.json.MappingJackson2HttpMessageConverter, org.springframework.http.converter.json.MappingJackson2HttpMessageConverter, org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter]
And the StringHttpMessageConverter has between its supported media types, the MediaType.ALL. Meaning that if the class is a String and the content-type is 'application/json' the StringHttpMessageConverter will execute before it can reach the MappingJackson2HttpMessageConverter, resulting in an invalid Json format.
I tried this from scratch with the spring initializer with the spring-boot-starter-web dependency with 2.1.3.RELEASE version.
Example:
@RestController
public class DemoController {
@GetMapping(value="try")
public ResponseEntity<String> demo(){
return ResponseEntity.ok("This is a string");
}
}
curl -X GET http://localhost:8080/try -H 'accept: application/json'
Response:
Body:This is a string
Content-Type →application/json;charset=UTF-8
When it should be:
Body:"This is a string"
Content-Type →application/json;charset=UTF-8
thanks
Affects: 2.1.3
1 votes, 2 watchers
The same for Spring Boot 2.3.1.RELEASE.
@RestController ResponseEntity<String> methods do not serve JSON body.
The plain string instead of JSON string in the response body comes as a bad surprise because it's inconsistent with how @RestController handles other types.