Reputation: 835
I have a Spring-Boot controller, which in turn makes a REST call to another service. Hence, there is a RestTemplate client inside the controller, which needs a Json-Root-Value-Wrap-And-Unwrap functionality.
Following common suggestions, I made a custome ObjectMapper like
@Configuration
public class CustomJsonMapper {
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToEnable(DeserializationFeature.UNWRAP_ROOT_VALUE);
return builder;
}
}
So I can auto-wire this class, and use in the RestTemplate, which is inside the controller. Hence the Controller looks somewhat like,
@RestController
@RequestMapping("uat")
public class UatController {
@Autowired
CustomObjectMapper customMapper;
@PostMapping(value = "startWork")
public ResponseEntity<?> startWork(@RequestBody startWorkInput startWorkInput) {
// Build the request
RestTemplate restTemp = new RestTemplate(factory);
restTemp.getMessageConverters().removeIf(m -> m.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));
restTemp.getMessageConverters().add(new MappingJackson2HttpMessageConverter(customMapper));
// Proceed to make client call
}
}
But, this causes the default ObjectMapper in SpringBoot to be over-ridden, I guess. Which is why I need to wrap the root value of input to this service as well.
Is there a way to use custom ObjectMapper without over-riding the default one.
Upvotes: 1
Views: 951
Reputation: 44962
If the mapper is localised to just one bean you can declare it as a field and not as a separate bean:
@RestController
@RequestMapping("uat")
public class UatController {
private final ObjectMapper customMapper = Jackson2ObjectMapperBuilder.json()
.featuresToEnable(DeserializationFeature.UNWRAP_ROOT_VALUE)
.build();
...
If you need to reuse you can try redefining the ObjectMapper
beans and marking the default one @Primary
:
@Configuration
public class CustomJsonMapper {
@Bean
@Primary
public ObjectMapper objectMapper() {
return Jackson2ObjectMapperBuilder.json().build();
}
@Bean
public ObjectMapper customObjectMapper() {
return Jackson2ObjectMapperBuilder.json()
.featuresToEnable(DeserializationFeature.UNWRAP_ROOT_VALUE)
.build();
}
}
however it's more complex than just localising the changes to the single controller that requires it. Moreover, it goes against the convention of auto-configuration in JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration
class.
Upvotes: 2