Search code examples
spring-mvcspring-bootdeserializationjackson2

Spring MVC: Deserialise query parameters to POJO using Jackson objectMapper


Spring web application configuration contains Jackson ObjectMapper configured like this

  objectMapper.disable(ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
  objectMapper.registerModule(new JavaTimeModule())

JavaTimeModule is added to handle deserialisation of ZonedDateTime. There are two endpoint which handle a POJO which contains ZonedDateTime. The POJO is like this:

class MyRequest {
  ZonedDateTime from
  ZonedDateTime to
}

and controller with endpoints is:

@Slf4j
@RestController
class MyController {

  @GetMapping('/pojo')
  void getPojo(MyRequest myRequest) {
    log.debug("Request received: $myRequest")
  }

  @PostMapping('/pojo')
  void postPojo(@RequestBody MyRequest myRequest) {
    log.debug("Request received: $myRequest")
  }
}

When I send POST /pojo with body

{"from": "2017-03-15T00:00:00Z", "to": "2017-03-16T00:00:00Z"}

The response is 200 and deserialisation is successful.

Contrary, when I send

GET /pojo?from=2017-03-15T00:00:00Z&to=2017-03-15T00:00:00Z

The 400 Bad Request is received with error

Failed to convert from type [java.lang.String] to type [java.time.ZonedDateTime] for value '2017-03-15T00:00:00Z'

This make sense, since in GET request, I'm not sending JSON and therefore JSON object mapper is not called.

Is there a way to use objectMapper for GET requests also, so query parameters are converted into POJO object?

By the way, I know that it can be deserialised for GET endpoint like below, but I want to use same converter for GET and POST endpoint

@DateTimeFormat(iso = ISO.DATE_TIME)
ZonedDateTime from
@DateTimeFormat(iso = ISO.DATE_TIME)
ZonedDateTime to

Solution

  • Injecting objectMapper and converting query parameters map into object solves the problem

    @Slf4j
    @RestController
    class MyController {
    
      @Autowired
      private ObjectMapper objectMapper
    
      @GetMapping('/pojo')
      void getPojo(@RequestParam Map<String, String> allRequestParams) {
        MyRequest request = objectMapper.convertValue(allRequestParams, MyRequest)
        log.debug("Request received: $myRequest")
      }
    ...