Jags
Jags

Reputation: 1761

Using different jackson ObjectMappers for seperate RequestMapping

I have a single @RequestMapping that consumes a custom MIME type. The request uses an ObjectMapper bean defined in the @Configuration to enabled the JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.

This feature allows typically invalid json (treating backslashes as a non-special character) to be consumed, which is a requirement of this particular @RequestMapping to allow google encoded polylines to be parsed directly. However this means that this ObjectMapper is now being used for ALL of my @RequestMapping when it is really only a requirement for one.

Is there a way to differentiate the ObjectMapper being used for each @Controller or @RequestMapping?

Object Mapper Bean

@Bean
public ObjectMapper objectMapper() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.featuresToEnable(
      JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER);

    return builder.build();
}

Request Mapping Interface Method

@ApiOperation(value = "Returns the toll cost breakdown for a journey", notes = "", response = TotalCost.class, tags={ "pricing", })
@ApiResponses(value = { 
    @ApiResponse(code = 200, message = "successful operation", response = TotalCost.class) })
@RequestMapping(value = "/pricing/journeyCost",
    produces = { "application/json" }, 
    consumes = { "application/vnd.toll-pricing+json" },
    method = RequestMethod.POST)
ResponseEntity<TotalCost> getTollBreakdownFromEncodedPoly(@ApiParam(value = "Request object representing the journey" ,required=true ) @RequestBody Journey body);

Upvotes: 4

Views: 3411

Answers (2)

Jags
Jags

Reputation: 1761

I found the answer in another stackoverflow question linked to me by another user - https://stackoverflow.com/a/45157169/2073800

I just had to add the following @Bean to my @Configuration

@Bean
public HttpMessageConverters customConverters() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.featuresToEnable(
      JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER);

    final AbstractJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(builder.build());
    converter.setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("application/vnd.toll-pricing+json")));

    return new HttpMessageConverters(converter);
}

Upvotes: 3

Abhijit Sarkar
Abhijit Sarkar

Reputation: 24647

If you've a custom MIME type, then you can register a custom HttpMessageConverter that uses a special ObjectMapper for your MIME type, and returns false from canRead/canWrite for regular MIME types. You register your custom HttpMessageConverter like so:

@EnableWebMvc
@Configuration
@ComponentScan
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(
      List<HttpMessageConverter<?>> converters) {

        messageConverters.add(myCustomMessageConverter());

        super.configureMessageConverters(converters);
    }
}

Think of it as related to content negotiation, and not related to URL mapping; URL mapping (@RequestMapping) is meant for finding a handler, not for choosing what marshaller/unmarshaller to use.

Upvotes: 1

Related Questions