在 Spring 环境中配置 Jackson 的 DeserializationProblemHandler
Configure a Jackson's DeserializationProblemHandler in Spring environment
据我了解,Spring 已经为 Jackson ObjectMapper
提供了一个 bean。因此,我没有创建新的 bean,而是尝试自定义这个 bean。
从这个 blog post, and then this Github project 我使用 Jackson2ObjectMapperBuilder
bean 来实现这个定制。
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.findModulesViaServiceLoader(true);
return builder;
}
然后,我试图自定义反序列化器以使其宽松:如果在反序列化 属性 时引发异常,我希望结果对象的 属性 为 null
并让反序列化继续(默认是在第一个无法反序列化的 属性 上失败)。
我已经能够通过扩展 DeserializationProblemHandler
的 class NullableFieldsDeserializationProblemHandler
实现这一点(我认为代码不相关,但如果需要,我可以分享) .
注册此处理程序的最简单方法是使用 ObjectMapper
的 .addHandler()
方法。但是当然,这样做,我需要在每次注入和使用 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());
}
}
但是这个解决方案的问题是我似乎仍然可以访问一个尚未注册问题处理程序的自动装配 ObjectMapper
(我可以在调试模式下需要它时看到它发生).
知道我应该如何注册这个处理程序吗?我注意到 Jackson2ObjectMapperBuilder
有一个 .handlerInstantiator()
,但我不知道如何使用它。
注意 我也尝试过 Jackson2ObjectMapperBuilderCustomizer 因为我正在使用 Spring 启动但没有更好的结果。
像这样写一个bean怎么样:
@Configuration
public class ObjectMapperConfiguration {
@Bean
ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// jackson 1.9 and before
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// or jackson 2.0
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
}
这是全局配置。相反,如果您想为特定的 class 配置功能,请在 class 定义上方使用此注释:
@JsonIgnoreProperties(ignoreUnknown = true)
无法通过 Jackson2ObjectMapperBuilder
或 Jackson2ObjectMapperBuilderCustomizer
直接将 DeserializationProblemHandler
添加到 ObjectMapper
。 handlerInstanciator()
方法用于其他用途。
但是,可以通过注册 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 已经为 Jackson ObjectMapper
提供了一个 bean。因此,我没有创建新的 bean,而是尝试自定义这个 bean。
从这个 blog post, and then this Github project 我使用 Jackson2ObjectMapperBuilder
bean 来实现这个定制。
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.findModulesViaServiceLoader(true);
return builder;
}
然后,我试图自定义反序列化器以使其宽松:如果在反序列化 属性 时引发异常,我希望结果对象的 属性 为 null
并让反序列化继续(默认是在第一个无法反序列化的 属性 上失败)。
我已经能够通过扩展 DeserializationProblemHandler
的 class NullableFieldsDeserializationProblemHandler
实现这一点(我认为代码不相关,但如果需要,我可以分享) .
注册此处理程序的最简单方法是使用 ObjectMapper
的 .addHandler()
方法。但是当然,这样做,我需要在每次注入和使用 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());
}
}
但是这个解决方案的问题是我似乎仍然可以访问一个尚未注册问题处理程序的自动装配 ObjectMapper
(我可以在调试模式下需要它时看到它发生).
知道我应该如何注册这个处理程序吗?我注意到 Jackson2ObjectMapperBuilder
有一个 .handlerInstantiator()
,但我不知道如何使用它。
注意 我也尝试过 Jackson2ObjectMapperBuilderCustomizer 因为我正在使用 Spring 启动但没有更好的结果。
像这样写一个bean怎么样:
@Configuration
public class ObjectMapperConfiguration {
@Bean
ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// jackson 1.9 and before
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// or jackson 2.0
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
}
这是全局配置。相反,如果您想为特定的 class 配置功能,请在 class 定义上方使用此注释:
@JsonIgnoreProperties(ignoreUnknown = true)
无法通过 Jackson2ObjectMapperBuilder
或 Jackson2ObjectMapperBuilderCustomizer
直接将 DeserializationProblemHandler
添加到 ObjectMapper
。 handlerInstanciator()
方法用于其他用途。
但是,可以通过注册 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());
}
}