Govind Somani Govind Somani - 6 months ago 148
JSON Question

Spring boot Jackson dynamic partial response

I am working on rest service using Spring-Boot 1.3. In this, I have to return partial response based on fields(to include) provided in request input parameter

(e.g. ../employees?opFields=name,emailId,..)
.

I want to implement
jackson.antpathfilter
(An implementation to add filtering based on AntPath matching). I have to add configuration such that I don't need to change return type of Rest(Controller)'s service method. But based on the object instance of particular class, serialize using filter else use normal serialization. Filter should be applied to instance of particular class only.

Update
Basically I want to implement dynamic partial response with,
1) Retrieving opFields dynamically from request.
2) Setting filter based on object type(can be antpathbuilder or simple)
3) Not changing return type of (rest)controller method.

As of now I have added configuration as below, but its giving issue in ExceptionHandler.

@Configuration
public class CustomDispatcherServlet extends WebMvcConfigurerAdapter {

@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> messageConverters) {
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().mixIn(Object.class, AntPathFilterMixin.class).build();
messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper));
extendMessageConverters(messageConverters);
}

}


I am extending MappingJacksonValue as below and using class object to send rest call response,

public class FilteredResponse extends MappingJacksonValue {

public FilteredResponse(final Object value, final String... opFields) {
super(value);
if (null == opFields || opFields.length <= 0) {
setFilters(new SimpleFilterProvider().addFilter("antPathFilter", new AntPathPropertyFilter("**")));
} else {
setFilters(new SimpleFilterProvider().addFilter("antPathFilter", new AntPathPropertyFilter(opFields)));
}
}
}


Doing so, giving me more issues, when object is not JacksonResponse class. Also, I have to create object at every controller method and change return type where partial response required.

Can we check object instance dynamically and set filter. Or any other solution?

Answer

Basically, when you extend MappingJacksonValue and set filters. E.g.

public class PartialResponse extends MappingJacksonValue {
  public JacksonResponse(final Object value, final String... filters) {
    super(value);
    if (null == filters || filters.length <= 0) {
      setFilters(new SimpleFilterProvider().addFilter("antPathFilter", new AntPathPropertyFilter("**")));
    } else {
      setFilters(new SimpleFilterProvider().addFilter("antPathFilter", new AntPathPropertyFilter(filters)));
    }
  }
}

In this, instead of configuring object mapper with Object.class, if you add configuration for PartialResponse.class, Resolves problem.

@Configuration
public class CustomDispatcherServlet extends WebMvcConfigurerAdapter {

 @Override
  public void configureMessageConverters(final List<HttpMessageConverter<?>> messageConverters) {
    ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().mixIn(PartialResponse.class, AntPathFilterMixin.class).build();
    messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper));
extendMessageConverters(messageConverters);
  }

}