spring-ws icon indicating copy to clipboard operation
spring-ws copied to clipboard

String response is not returned with a valid JSON format [SWS-1062]

Open gregturn opened this issue 7 years ago • 1 comments

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

gregturn avatar Mar 20 '19 19:03 gregturn

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.

pekuz avatar Feb 12 '21 13:02 pekuz