Search code examples
springspring-mvcspring-bootspring-restcontrollerspring-rest

Spring MVC: let RestController serialize different classes to JSON


Just for the sake of an example let's assume I want to create a REST endpoint which returns the message of the day (motd). The incoming parameter is the day represented by a number, the outcome is JSON which contains the day and the message.

public class Motd {
  int day;
  String message;
  ...
}

This gets translated into ...

{ 
  "day": 1,
  "message": "whatever you want to say here"
}

... and is returned by this code:

@RequestMapping(value = "/motd", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Motd> getMotd(@RequestParam(value = "day") int day {
    ...
    return new ResponseEntity<Motd>(motd, HttpStatus.OK);
}

This works fine as long everything is ok but my intention is to return both a http status code and a JSON explaining the reason for any errors that might occur:

...
if( day > 365 ) {
    Status error = new Status( "failed", "can't go beyond 365 days" );
    return new ResponseEntity<Status>(error, HttpStatus.BAD_REQUEST);
}
...

But this conflicts with the ResponseEntity<Motd> defined earlier. The only solution I know so far is to define ResponseEntity<String> and serialize the JSON on my own. Are there any alternatives / more elegant alternatives which allow Spring return "varying" classes ?

The emphasis of my question is not on error handling, I was shown some clever ways to do this based on exceptions for example. And if possible I want to avoid deriving all possible returned classes from a common base class.

My code is based on Spring Boot 1.3 RC1.


Solution

  • In the case of ResponseEntity, Spring MVC does not care about the parameterized return type, it cares only about the value.

    You can simply provide

    public ResponseEntity<?> getMotd(@RequestParam(value = "day") int day {
    

    Spring MVC's HttpEntityMethodProcessor, which handles values returned by your handler methods that are of type ResponseEntity, will retrieve the body of the ResponseEntity and delegate writing to the response to an appropriate HttpMessageConverter.

    The same process will happen for an Motd value as it will for a Status value.