Best Practices for JSON String Response
Wrapping a String in an Object
Get classy and avoid manual quote escapes:
@RestController
public class ClassResponseController {
@GetMapping("/classStringAsJson")
public Response getMessage () {
return new Response( "When life gives you classes, make objects." );
}
static class Response {
private final String message;
public Response (String message) {
this .message = message;
}
public String getMessage () {
return this .message;
}
}
}
Fancy ResponseEntity
With ResponseEntity
, gain extra control:
@RestController
public class ResponseEntityController {
@GetMapping("/responseEntityAsString")
public ResponseEntity<String> getResponseEntityAsString () {
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(JSONObject.quote( "When life gives you lemons, JSONify them!" ));
}
}
Here JSONObject.quote()
ensures its input turns into a valid JSON text.
JSONify it with Collections.singletonMap
Perfect for a one-off key-value JSON object:
@RestController
public class SingletonMapController {
@GetMapping("/singletonMap")
public Map<String, String> getSingletonMap () {
return Collections.singletonMap( "message" , "Hello, Singleton World!" );
}
}
Delve Deeper with Advanced Configuration
To take JSON conversion into our own hands:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters (List<HttpMessageConverter<?>> converters) {
// Sorting hat code to choose Jackson converter over String converter
}
}
Mastering the Art of JSON Handling
RestyGWT Compatibility
Work with RestyGWT ? Make sure the returned JSON is appetizing :
@GetMapping(value = "/restyGwtFriendly", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getRestyGWTCompatibleString () {
return ResponseEntity.ok( new JSONObject(Map.of( "response" , "Respecting the Rest(yGWT)!" )));
}
Debugging Served on a Platter
Just like ketchup to fries, a logger nicely accompanies debugging :
private static final Logger logger = LoggerFactory.getLogger(YourController.class);
@GetMapping("/loggableStringAsJson")
public Map<String, String> getLoggableStringAsJson (HttpServletRequest request) {
logger.info( "Received order from {}" , request.getRemoteAddr());
return Collections.singletonMap( "response" , "Order up! Hello, World!" );
}
Handle Content with Elegance
Give your content negotiation a VIP upgrade :
@GetMapping("/negotiatedStringAsJson")
public ResponseEntity<String> getNegotiatedStringAsJson () {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<>( "{\"message\":\"The Art of Negotiation, JSON style!\"}" , headers, HttpStatus.OK);
}
Taking the JSON Path with Custom Conversion
Snap StringHttpMessageConverter
out of default conversion for pure JSONness:
@Override
public void configureMessageConverters (List<HttpMessageConverter<?>> converters) {
converters.removeIf(httpMessageConverter -> httpMessageConverter instanceof StringHttpMessageConverter);
// Configure your mighty Jackson converter
}