Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't set ProblemHandler to ObjectMapper in Spring Boot

I tried to add custom problem handler to object mapper with Jackson2ObjectMapperBuilderCustomizer:

@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder builder) {
            ObjectMapper m = builder.build();
            m.addHandler(
                    new DeserializationProblemHandler() {
                        @Override
                        public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException {
                            System.out.println("ahahahaa");
                            return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
                        }
                    }
            );
        }
    };
}

But when i autowired ObjectMapper bean _problemHandlers property is null.

I also tried just customize existed ObjectMapper with:

@Autowired
public customize(ObjectMapper mapper) {
...
}

But result is the same. I don't know who can erasure this property. I don't initialize another builders/factories/etc of object mapper in another place at all. What i'm doing wrong?

like image 346
DamienMiheev Avatar asked Oct 09 '17 10:10

DamienMiheev


1 Answers

It's not possible to directly add a DeserializationProblemHandler to the ObjectMapper via a Jackson2ObjectMapperBuilder or Jackson2ObjectMapperBuilderCustomizer. Calling build() on the builder is a no-go, since the resulting ObjectMapper is local to the method: Spring itself will call build() later, creating another ObjectMapper instance.

However, it's possible to do so by registering a Jackson module :

  • the builder has a modules() method
  • the module has access via setupModule() to a SetupContext instance, which has a addDeserializationProblemHandler() method

This should then work

@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder builder) {
            builder.modules(new MyModule());
        }
    };
}

private static class MyModule extends SimpleModule {
    @Override
    public void setupModule(SetupContext context) {
        // Required, as documented in the Javadoc of SimpleModule
        super.setupModule(context);
        context.addDeserializationProblemHandler(new MyDeserializationProblemHandler());
    } 
}

private static class MyDeserializationProblemHandler extends DeserializationProblemHandler {
    @Override
    public boolean handleUnknownProperty(DeserializationContext ctxt,
                                         JsonParser p,
                                         JsonDeserializer<?> deserializer,
                                         Object beanOrClass,
                                         String propertyName)
            throws IOException {
        System.out.println("ahahahaa");
        return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
    }
}

EDIT (2022-06-27)

As mentioned by E-Riz in the comments, with newer Spring Boot versions you can just register the module as a Spring Bean and it will be configured on the ObjectMapper with all the other modules.

// Or declare it as a @Bean in a @Configuration
@Component
public class MyModule extends SimpleModule {
    @Override
    public void setupModule(SetupContext context) {
        // Required, as documented in the Javadoc of SimpleModule
        super.setupModule(context);
        context.addDeserializationProblemHandler(new MyDeserializationProblemHandler());
    } 

    private static class MyDeserializationProblemHandler extends DeserializationProblemHandler {
        @Override
        public boolean handleUnknownProperty(DeserializationContext ctxt,
                                             JsonParser p,
                                             JsonDeserializer<?> deserializer,
                                             Object beanOrClass,
                                             String propertyName)
                throws IOException {
            System.out.println("ahahahaa");
            return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
        }
    }
}
like image 119
Frank Pavageau Avatar answered Oct 17 '22 03:10

Frank Pavageau