Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot : Different ObjectMapper instances for Request and Response

I have following controller in my spring boot application:

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<ResponseDto<MyClass> process(@RequestBody RequestDto<MyClass> request){
    return null;
}

MyClass has a field, let's say 'myField' and I want different NamingStrategyconfiguration for request and response for this field (this is because I don't want to create a new class just for one field). I have configured ObjectMapper instance as below:

@Bean
public ObjectMapper objectMapper(){
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setPropertyNamingStrategy(namingStrategy);
    return objectMapper;
}

This will be used both for Request and Response (i.e. deserialization and serialization), is there any way in spring boot by which I can instruct the controller to use different ObjectMapper instances?

like image 591
Darshan Mehta Avatar asked Mar 09 '17 09:03

Darshan Mehta


People also ask

Should I reuse ObjectMapper?

Note that copy() operation is as expensive as constructing a new ObjectMapper instance: if possible, you should still pool and reuse mappers if you intend to use them for multiple operations.

Can we Autowire ObjectMapper spring boot?

If you're working with Spring Boot, there's a section in the manual dedicated to working with the ObjectMapper If you create a default Jackson2ObjectMapperBuilder @Bean , you should be able to autowire that same ObjectMapper instance in your controller.

Is ObjectMapper thread safe?

ObjectMapper is a completely thread-safe service class, it is meant to be used as singleton across the lifetime of the application. It is also very expensive to create.


1 Answers

You can solve it with content negotiation. Firstly, define your custom HttpMessageConverter. In following example I have defined a custom converter that is applied when the request Content-Type header is set to application/test+json:

@Bean
public HttpMessageConverters customConverters() {
    final AbstractJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(new ObjectMapper());
    converter.setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("application/test+json")));

    return new HttpMessageConverters(true, Collections.singletonList(converter));
}

For simplicity of this example I've used newly created ObjectMapper - in your case you will have to pass here previously configured object.

Next thing is to tell your action to accept only appliction/test+json requests (keep in mind, that from now on it requires to Content-Type:application/test+json header to present in every request to this endpoint):

@RequestMapping(method = RequestMethod.POST, consumes = "application/test+json")
public ResponseEntity<ResponseDto<MyClass> process(@RequestBody RequestDto<MyClass> request){
    return null;
}

Last thing is to make sure that when you call this endpoint, Content-Type:application/test+json header is set. Of course you can use any other name for desired content type, presented name is just an example.

like image 123
Szymon Stepniak Avatar answered Sep 25 '22 01:09

Szymon Stepniak