[英]Can't set ProblemHandler to ObjectMapper in Spring Boot
I tried to add custom problem handler to object mapper with Jackson2ObjectMapperBuilderCustomizer:我尝试使用 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.但是当我自动装配 ObjectMapper bean _problemHandlers 属性为空时。
I also tried just customize existed ObjectMapper with:我还尝试使用以下方法自定义现有的 ObjectMapper:
@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?
我做错了什么?
It's not possible to directly add a DeserializationProblemHandler
to the ObjectMapper
via a Jackson2ObjectMapperBuilder
or Jackson2ObjectMapperBuilderCustomizer
.无法通过
Jackson2ObjectMapperBuilder
或Jackson2ObjectMapperBuilderCustomizer
直接将DeserializationProblemHandler
添加到ObjectMapper
。 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.在构建器上调用
build()
是不行的,因为生成的ObjectMapper
是该方法的本地:Spring 本身稍后会调用build()
,创建另一个ObjectMapper
实例。
However, it's possible to do so by registering a Jackson module :但是,可以通过注册 Jackson 模块来做到这一点:
modules()
methodmodules()
方法setupModule()
to a SetupContext
instance, which has a addDeserializationProblemHandler()
methodsetupModule()
访问SetupContext
实例,该实例具有addDeserializationProblemHandler()
方法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)编辑 (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 .正如 E-Riz 在评论中提到的,对于较新的 Spring Boot 版本,您只需将模块注册为 Spring Bean,它将在
ObjectMapper
上与所有其他模块一起配置。
// 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);
}
}
}
I am new to Spring Boot
, then, it was difficult to understand how I could use this.我是
Spring Boot
的新手,因此很难理解如何使用它。 But after some research I managed to figure out.但经过一番研究,我设法弄清楚了。
I had to create a class named src.main.java.com.applicationname.config.JacksonUnknownPropertyConfig.java
with the contents:我必须创建一个名为
src.main.java.com.applicationname.config.JacksonUnknownPropertyConfig.java
的类,其内容为:
package com.applicationname.config;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.server.ResponseStatusException;
import java.io.IOException;
@SpringBootConfiguration
public class JacksonUnknownPropertyConfig {
private static final Logger logger = LoggerFactory.getLogger(JacksonUnknownPropertyConfig.class);
@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");
final String missing = String.format("Unknown request property '%s'", propertyName);
logger.warn(missing);
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, missing);
}
return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
}
}
}
And I also had to add FAIL_ON_UNKNOWN_PROPERTIES
to the file src.main.resources.application.properties
而且我还必须将
FAIL_ON_UNKNOWN_PROPERTIES
添加到文件src.main.resources.application.properties
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true
After this, looks like Sprint Boot
automatically recognizes the new class I created and correctly loads it.在此之后,看起来
Sprint Boot
会自动识别我创建的新类并正确加载它。
2020-07-20 23:41:22.934 INFO 16684 --- [ task-1] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-07-20 23:41:22.944 TRACE 16684 --- [ task-1] o.h.type.spi.TypeConfiguration$Scope : Handling #sessionFactoryCreated from [org.hibernate.internal.SessionFactoryImpl@3edd0926] for TypeConfiguration
2020-07-20 23:41:22.946 INFO 16684 --- [ task-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-07-20 23:41:23.209 INFO 16684 --- [ main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-07-20 23:41:23.222 INFO 16684 --- [ main] c.a.p.AppointmentPublishingApplication : Started AppointmentPublishingApplication in 6.445 seconds (JVM running for 7.615)
2020-07-20 23:41:26.229 INFO 16684 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-07-20 23:41:26.229 INFO 16684 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-07-20 23:41:26.236 INFO 16684 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 7 ms
ahahahaa
Related threads:相关话题:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.