7

As mentioned for example in RFC 7159, strings etc primitive types are valid json messages on their own. But the string has to be encased in double quotes.

So, string:

test

in json is:

"test"

If I send a properly quoted POST body

"test"

to the following code

@RestController
@RequestMapping("test")
public class TestController{
    @RequestMapping(method=RequestMethod.POST)
    public ResponseEntity<?> userLogout(@RequestBody final String input) {
        System.out.println(input);
        return new ResponseEntity<>("OK", HttpStatus.OK);
    }
}

the value of input variable is

"test"

instead of

test

which would be the correct value.

Also the output of the request is

OK

instead of

"OK"

which would be the correct output.

Any ideas how to force Spring to handle the strings properly?

The request does have the correct header:

Content-Type: application/json; charset=UTF-8

And adding produces="application/json" to the RequestMapping annotation didn't help.

(Just a side note: If you use retrofit or Gson for communication, they do handle strings properly.)

Groosa
  • 301
  • 3
  • 8
  • 1
    Possible duplicate of [Simple string as JSON return value in spring rest controller](http://stackoverflow.com/questions/23581619/simple-string-as-json-return-value-in-spring-rest-controller) – Krzysztof Krasoń Jun 28 '16 at 18:44
  • Does this help? http://stackoverflow.com/questions/18385361/return-json-for-responseentitystring Also try adjusting the consumption media type – Bernhard Jun 28 '16 at 18:51
  • @Bernhard no, that doesn't help, and in that question there is no solution – Groosa Jun 28 '16 at 19:03
  • @krzyk yes, half of the question seems to be duplicate. – Groosa Jun 28 '16 at 19:04

1 Answers1

12

String is a special type for Spring MVC.

When trying to produce an argument for a @RequestBody annotated parameter, Spring MVC choose from a list of default or custom HttpMessageConverter implementations. Two of these are relevant for your example (ordered this way): StringHttpMessageConverter and MappingJackson2HttpMessageConverter (or the Gson equivalent).

StringHttpMessageConverter supports all media types and will therefore be used to read the raw text from your request, which is "test", and provide that value as an argument.

You can provide your own list of HttpMessageConverter objects in the order you want. If you put MappingJackson2HttpMessageConverter first, then it would be able to parse your JSON as a String and produce the String argument value test.

If you don't want to go through those hoops, you can also change your parameter to the Jackson type corresponding to a JSON string, TextNode and then retrieve its value.

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> userLogout(@RequestBody final TextNode input) {
    System.out.println(input.asText());
    return new ResponseEntity<>("OK", HttpStatus.OK);
}

The same applies for the response. The value "OK" is a String and will be handled with a StringHttpMessageConverter. Use a TextNode or reorder your HttpMessageConverter list.

return new ResponseEntity<>(new TextNode("OK"), HttpStatus.OK);
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724