我尝试使用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属性为null。
我也试过用以下方法定制现有的ObjectMapper:
@Autowired
public customize(ObjectMapper mapper) {
...
}
但结果是一样的。我不知道谁可以擦除这个属性。我根本不在另一个地方初始化对象映射器的另一个构建器/工厂/等。我做错了什么?
答案 0 :(得分:5)
无法通过DeserializationProblemHandler
或ObjectMapper
直接向Jackson2ObjectMapperBuilder
添加Jackson2ObjectMapperBuilderCustomizer
。在构建器上调用build()
是不行的,因为生成的ObjectMapper
是方法的本地:Spring本身稍后将调用build()
,创建另一个ObjectMapper
实例。 / p>
但是,可以通过注册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);
}
}
答案 1 :(得分:0)
我是 Spring Boot
的新手,所以很难理解如何使用它。但是经过一番研究,我设法弄清楚了。
我必须创建一个名为 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);
}
}
}
我还必须将 FAIL_ON_UNKNOWN_PROPERTIES
添加到文件 src.main.resources.application.properties
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true
此后,看起来 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
相关线程: