无法在 Spring 引导中将 ProblemHandler 设置为 ObjectMapper
Can't set ProblemHandler to ObjectMapper in Spring Boot
我尝试使用 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);
}
}
);
}
};
}
但是当我自动装配 ObjectMapper bean 时,_problemHandlers 属性 为空。
我还尝试使用以下方法自定义现有的 ObjectMapper:
@Autowired
public customize(ObjectMapper mapper) {
...
}
但结果是一样的。不知道谁能把这个擦掉属性。我根本没有在另一个地方初始化另一个 builders/factories/etc 对象映射器。我做错了什么?
无法通过 Jackson2ObjectMapperBuilder
或 Jackson2ObjectMapperBuilderCustomizer
直接将 DeserializationProblemHandler
添加到 ObjectMapper
。在构建器上调用 build()
是不行的,因为生成的 ObjectMapper
是方法本地的:Spring 本身稍后会调用 build()
,创建另一个 ObjectMapper
实例。
但是,可以通过注册 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 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);
}
}
我是Spring Boot
的新手,当时很难理解我如何使用它。但经过一些研究,我设法弄清楚了。
我必须创建一个名为 src.main.java.com.applicationname.config.JacksonUnknownPropertyConfig.java
的 class,其内容为:
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);
}
}
}
而且我还必须将 FAIL_ON_UNKNOWN_PROPERTIES
添加到文件 src.main.resources.application.properties
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true
在此之后,看起来 Sprint Boot
自动识别我创建的新 class 并正确加载它。
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
相关话题:
- jackson Unrecognized field
- Ignoring new fields on JSON objects using Jackson
- Spring Data Elastic - Java.Time.Instant class Jackson deserliization not working
- Enable Jackson Deserialization of Empty Objects to Null
- How do you globally set Jackson to ignore unknown properties within Spring?
- https://www.baeldung.com/spring-bean
- https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-spring-mvc
我尝试使用 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);
}
}
);
}
};
}
但是当我自动装配 ObjectMapper bean 时,_problemHandlers 属性 为空。
我还尝试使用以下方法自定义现有的 ObjectMapper:
@Autowired
public customize(ObjectMapper mapper) {
...
}
但结果是一样的。不知道谁能把这个擦掉属性。我根本没有在另一个地方初始化另一个 builders/factories/etc 对象映射器。我做错了什么?
无法通过 Jackson2ObjectMapperBuilder
或 Jackson2ObjectMapperBuilderCustomizer
直接将 DeserializationProblemHandler
添加到 ObjectMapper
。在构建器上调用 build()
是不行的,因为生成的 ObjectMapper
是方法本地的:Spring 本身稍后会调用 build()
,创建另一个 ObjectMapper
实例。
但是,可以通过注册 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 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);
}
}
我是Spring Boot
的新手,当时很难理解我如何使用它。但经过一些研究,我设法弄清楚了。
我必须创建一个名为 src.main.java.com.applicationname.config.JacksonUnknownPropertyConfig.java
的 class,其内容为:
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);
}
}
}
而且我还必须将 FAIL_ON_UNKNOWN_PROPERTIES
添加到文件 src.main.resources.application.properties
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true
在此之后,看起来 Sprint Boot
自动识别我创建的新 class 并正确加载它。
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
相关话题:
- jackson Unrecognized field
- Ignoring new fields on JSON objects using Jackson
- Spring Data Elastic - Java.Time.Instant class Jackson deserliization not working
- Enable Jackson Deserialization of Empty Objects to Null
- How do you globally set Jackson to ignore unknown properties within Spring?
- https://www.baeldung.com/spring-bean
- https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-spring-mvc