Let's try the straightforward way first. Take a look at the following code:
@Controller
public class HelloWorldController {
@RequestMapping("/api/greeting/fakeJson")
@ResponseBody
public String fakeJson() {
return "{\"message\":\"Hello world\"}";
}
}
The only thing that changed here is the returned string. It now contains JSON, with a log of backslashes to encode the necessary double quotes within a Java string. The result of the request, then, is as follows:
GET /api/greeting HTTP/1.1
Content-Length: 25
Content-Type: text/plain;charset=UTF-8
{"message":"Hello world"}
There are a few things to criticize here. The first thing is that the JSON is cumbersome to write. Java makes this very hard because the embedded double quotes need to be escaped. JSON may be a reasonably easy format, but, still, particularly for bigger data structures than the one returned here, creating it by hand is error-prone.
Second, and more importantly, the content type is still set to plain text! Some clients may ignore the Content-Type header anyway and just expect JSON to be returned, and those clients will work with our faulty server. Well-behaved clients, however, will not recognize it as JSON. They may accept it as text (albeit weird text) or altogether reject it.
Postman, for instance, honors the Content-Type header. By default, it will show the output of a call to this controller as plain text. You may, however, choose JSON by hand, thereby overriding the detected Content-Type.
In rare circumstances, this might be a quick hack to satisfy some required interface, but surely we can do much better!