2

In our company library (say lib-a) we have an interface:

public interface MyInterface {
    ...
}

and its default implementation:

public enum DefaultMyImpl implements MyInterface {
    ...
}

a serializer for it:

public class DefaultMyInterfaceSerializer extends JsonDeserializer<MyInterface> {
    @Override
    public MyInterface deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        return parser.readValuesAs(DefaultMyImpl.class).next();
    }
}

and for Jackson we have:

@Bean
public Jackson2ObjectMapperBuilderCustomizer defaultObjectMapperBuilderCustomizer() {
    return builder -> builder
            .deserializerByType(MyInterface.class, new DefaultMyInterfaceSerializer());
}

and in a child project that has a dependency on lib-a, we might have another implementation:

public enum ChildMyImpl implements MyInterface {
    ...
}

and a serializer for it:

public class ChildMyInterfaceSerializer extends JsonDeserializer<MyInterface> {
    @Override
    public MyInterface deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        return parser.readValuesAs(ChildMyImpl.class).next();
    }
}

and it's related Jackson configuration:

@Bean
public Jackson2ObjectMapperBuilderCustomizer childObjectMapperBuilderCustomizer() {
    return builder -> builder
            .deserializerByType(MyInterface.class, new ChildMyInterfaceDeserializer());
}

However, I don't seem to be able to override Jackson2ObjectMapperBuilder deserializer for MyInterface. I'm getting this Http 400 error on deserialization:

Bad Request: JSON parse error: Cannot deserialize value of type `com.company.library.domain.DefaultMyImpl` from String "SOME_STRING": not one of the values accepted for Enum class: [DEFAUL_ENUM_VAL]
 at [Source: (PushbackInputStream); line: 1, column: 30]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize value of type `com.company.library.domain.DefaultMyImpl` from String "SOME_STRING": not one of the values accepted for Enum class: [DEFAUL_ENUM_VAL]
 at [Source: (PushbackInputStream); line: 1, column: 30] (through reference chain: com.company.library.domain.MyInterface["..."])

Thinking it is because the customizer in the library overrides the child project's I've tried putting:

@DependsOn(value = "defaultObjectMapperBuilderCustomizer")

or

@Order(value = Ordered.HIGHEST_PRECEDENCE)

on top of child customizer @Bean to no avail. How do I order them in the way that child project overrides the one in the dependency (lib-a)?

Hasan Can Saral
  • 2,950
  • 5
  • 43
  • 78

1 Answers1

0

I had to implement BeanPostProcessor and override it there:

@Configuration
public class FinalJacksonConfiguration implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Jackson2ObjectMapperBuilder) {
            final Jackson2ObjectMapperBuilder builder = (Jackson2ObjectMapperBuilder) bean;
            builder.serializerByType(MyInterface.class, new ChildMyInterfaceDeserializer());
        }
        return bean;
    }
}

Hasan Can Saral
  • 2,950
  • 5
  • 43
  • 78