Customize Spring @RequestParam Deserialization for Maps and/or Nested Objects Customize Spring @RequestParam Deserialization for Maps and/or Nested Objects spring spring

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.