spring - 在 Spring 环境中配置 Jackson 的 DeserializationProblemHandler

标签 spring spring-boot jackson jackson2 jackson-databind

<分区>

据我了解,Spring 已经为 Jackson ObjectMapper 提供了一个 bean。因此,我没有创建新的 bean,而是尝试自定义这个 bean。

从这里blog post ,然后是这个 Github project我使用 Jackson2ObjectMapperBuilder bean 来实现这种定制。

@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.findModulesViaServiceLoader(true);
    return builder;
}

然后,我试图自定义反序列化器以使其宽松:如果在反序列化属性时引发异常,我希望结果对象的属性为 null 并让反序列化继续(默认是在无法反序列化的第一个属性上失败)。

我已经能够通过扩展 DeserializationProblemHandler 的类 NullableFieldsDeserializationProblemHandler 实现这一点(我认为代码不相关,但如果需要,我可以分享它) .

注册此处理程序的最简单方法是使用ObjectMapper.addHandler() 方法。但是,当然,这样做,我需要在每次注入(inject)和使用 ObjectMapper 时进行设置。我希望能够配置处理程序,以便每次 ObjectMapper 自动连接时,处理程序已经存在。

到目前为止,我想到的最佳解决方案是仅使用 @PostConstruct 注释来注册问题处理程序。

@Configuration
public class JacksonConfiguration implements InitializingBean {

  @Autowired private ObjectMapper objectMapper;

  @Bean
  public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.findModulesViaServiceLoader(true);
    return builder;
  }

  @Override
  public void afterPropertiesSet() {
    objectMapper.addHandler(new NullableFieldsDeserializationProblemHandler());
  }
}

但这个解决方案的问题是,我似乎仍然可以访问一个尚未注册问题处理程序的 Autowiring ObjectMapper(我可以在调试中需要它时看到它发生模式)。

知道我应该如何注册这个处理程序吗?我注意到 Jackson2ObjectMapperBuilder 有一个 .handlerInstantiator() 但我不知道如何使用它。

注意 我也试过 Jackson2ObjectMapperBuilderCustomizer因为我使用的是 Spring Boot 但没有更好的结果。

最佳答案

不可能通过 Jackson2ObjectMapperBuilderJackson2ObjectMapperBuilderCustomizer 直接将 DeserializationProblemHandler 添加到 ObjectMapperhandlerInstanciator() 方法用于其他用途。

但是,可以通过注册 Jackson 模块来实现:

  • 构建器有一个 modules() 方法
  • 该模块可以通过 setupModule() 访问 SetupContext 实例,该实例具有 addDeserializationProblemHandler() 方法

这个有效:

@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 NullableFieldsDeserializationProblemHandler());
    } 
}

关于spring - 在 Spring 环境中配置 Jackson 的 DeserializationProblemHandler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48773728/

相关文章:

java - 使用存储过程快速从sql server读取百万条记录并使用java和spring boot将其写入csv

java如何在类之间共享字段和方法

java - Jackson Json 反序列化 : Unrecognized field "..." , 未标记为可忽略

java - 为什么我的 "index.jsp"无法使用 java 和 Spring 识别 Controller 中的变量

java - Spring 后处理器,顺序,@Required

Spring WS 的 JavaScript 客户端

spring-boot - 如何告诉 RSocket 通过由阻塞队列支持的 Java 8 Stream 读取数据流

java - 升级到 Hibernate 4 后出现错误 "commit failed"

java - 如何在 Spring Data JPA 中表示带有空值的表?

Java Spring STOMP MessageMapping 未被调用