如何在子项目中覆盖自定义 Jackson 反序列化器?

发布于 2025-01-18 02:56:50 字数 2565 浏览 0 评论 0原文

在我们公司的库(例如lib-a)中,我们有一个接口:

public interface MyInterface {
    ...
}

及其默认实现:

public enum DefaultMyImpl implements MyInterface {
    ...
}

它的序列化器:

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

对于Jackson,我们有:

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

并且在一个依赖于的子项目中>lib-a,我们可能有另一个实现:

public enum ChildMyImpl implements MyInterface {
    ...
}

以及它的序列化器:

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

并且它与 Jackson 配置相关:

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

但是,我似乎无法覆盖 Jackson2ObjectMapperBuilder 反序列化器我的界面。我在反序列化时收到此 Http 400 错误:

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["..."])

认为这是因为库中的自定义程序覆盖了我尝试放置的子项目:

@DependsOn(value = "defaultObjectMapperBuilderCustomizer")

@Order(value = Ordered.HIGHEST_PRECEDENCE)

在子自定义程序 @Bean 之上,但无济于事。如何以子项目覆盖依赖项 (lib-a) 中的项目的方式对它们进行排序?

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)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半世蒼涼 2025-01-25 02:56:50

我必须实现beanpostProcessor并在此处覆盖它:

@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;
    }
}

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;
    }
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文