无法在 Spring Boot 中将 ProblemHandler 设置为 ObjectMapper
Posted
技术标签:
【中文标题】无法在 Spring Boot 中将 ProblemHandler 设置为 ObjectMapper【英文标题】:Can't set ProblemHandler to ObjectMapper in Spring Boot 【发布时间】:2018-03-20 12:35:13 【问题描述】:我尝试使用 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)
...
但结果是一样的。我不知道谁能删除这个属性。我根本不会在另一个地方初始化对象映射器的另一个构建器/工厂/等。我做错了什么?
【问题讨论】:
【参考方案1】:无法通过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);
【讨论】:
嗨,我使用了你的代码。但是当我的请求包含无效的 JSON 字段时,控制不会进入handleUnknownProperty
。我在这里错过了什么吗?
context.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
也许?这取决于它在做什么。【参考方案2】:
我是 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
相关话题:
-
Spring Boot, Spring MVC JSON RequestBody: Unknown property ignored
How to customise Jackson in Spring Boot 1.4
jackson Unrecognized field
Ignoring new fields on JSON objects using Jackson
Configure FAIL_ON_UNKNOWN_PROPERTIES for each RequestMapping differently in the Controller
Jackson deserializer priority?
Spring Data Elastic - Java.Time.Instant class Jackson deserliization not working
Enable Jackson Deserialization of Empty Objects to Null
Spring RestController : reject request with unknown fields
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
【讨论】:
以上是关于无法在 Spring Boot 中将 ProblemHandler 设置为 ObjectMapper的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 Hibernate 在 Spring Boot 中将 MongoDB 设置为自动递增
Spring Boot 应用程序无法在 Docker 中将事件发布到 Kafka
如何在 Wildfly 中将外部属性文件加载到 Spring Boot