Customize Spring @RequestParam Deserialization for Maps and/or Nested Objects
Spring Boot supports the use of dot-separated paths to bind maps thanks to its custom DataBinder
subclass, RelaxedDataBinder. The good news is that its also a DataBinder
that's used in Spring MVC to perform the request parameter binding. The bad news is that plugging in your own binder isn't straightforward and that it needs to be a WebDataBinder
. You can plug one in by declaring your own RequestMappingHandlerAdapter
bean named requestMappingHandlerAdapter
. For example:
@Beanpublic RequestMappingHandlerAdapter requestMappingHandlerAdpter() { return new RequestMappingHandlerAdapter() { @Override protected InitBinderDataBinderFactory createDataBinderFactory( List<InvocableHandlerMethod> binderMethods) throws Exception { return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer()) { @Override protected ServletRequestDataBinder createBinderInstance( final Object target, String objectName, NativeWebRequest request) { return new ServletRequestDataBinder(target) { private RelaxedDataBinder relaxedBinder = new RelaxedDataBinder(target); @Override protected void doBind(MutablePropertyValues mpvs) { this.relaxedBinder.bind(mpvs); } }; } }; } };}
You may well want to refactor this to avoid the use of multiple nested anonymous inner classes, but it hopefully illustrates the general approach.
@InitBinderprivate void initBinder(WebDataBinder binder, ServletRequest request) { new RelaxedDataBinder(binder.getTarget()).bind(new ServletRequestParameterPropertyValues(request));}
This is how I got away with it; a method in the controller delegating to a RelaxedDataBinder
.