I'm using Spring MVC 4.3.2 with @RestController and I would like to be able to dynamically filter JSON properties specified by our clients in the request.
To keep things easy, let's say I have a Person POJO that contains firstName and lastName fields. This POJO is generated, that's why you will see that I'm using a mixin.
Let's say one client want to retrieve all the persons' firstName, he will call our rest endpoint like this : http://localhost/persons&fields=firstName. And the json will only contains the firstName, not the lastName fields.
Here is my Controller:
@RestController
public class RestPersonController implements PersonApi {
@Autowired
private PersonService personService;
@Autowired
private ObjectMapper objectMapper;
@Override
@GetMapping(path = "/persons")
public ResponseEntity<List<Person>> getPersons(
@RequestParam(required = false) String fields) {
List<Person> persons = this.personService.getPersons();
// Filter fields
if (StringUtils.isNotBlank(fields)) {
configureFilter(fields);
}
return ResponseEntity.status(HttpStatus.OK).body(persons);
}
private void configureFilter(String fields) {
Set<String> fieldsToKeep = new HashSet<>();
fieldsToKeep.add(fields);
objectMapper.addMixIn(Person.class, PersonDynamicFilterMixIn.class);
FilterProvider filterProvider = new SimpleFilterProvider().
addFilter("dynamicFilter", SimpleBeanPropertyFilter.filterOutAllExcept(fieldsToKeep));
objectMapper.setFilterProvider(filterProvider);
}
}
As you can see, the return of the method is ResponseEntity<List<Person>>
(I can't change it to JacksonMappingValue
, it is from the PersonApi interface) and we are returning with ResponseEntity.status(HttpStatus.OK).body(persons)
(so I can't manually write the JSON response with the objectMapper myself);.
Under the hood, Spring is using Jackson ObjectMapper to do the conversion. I would like to configure that ObjectMapper when the fields request parameter is specified.
I also want the ObjectMapper configuration to be the same as Spring's default.
I can't use JsonViews because otherwise it is not dynamic anymore.
Could someone show me how I need to configure Spring to do that ? I tried to use these kind of things in SpringConfiguration, but then I end up with some of my tests not working anymore. For some tests, if I run a single test it passes, if I run the whole test suite that test doesn't pass anymore ...
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter(objectMapper()));
}
@Bean
public ObjectMapper objectMapper() {
return Jackson2ObjectMapperBuilder.json().build();
}
Thank you for your help !