Spring Boot无法解析OffsetDateTime作为REST服务参数问题
Spring Boot 3中OffsetDateTime请求参数转换失败
环境信息
Springboot 3.0.3 OpenJdk-17
问题详情
定义了一个接收OffsetDateTime类型请求参数的REST接口:
@GetMapping("/transaction/search/bydate") public String searchTransactions( @RequestParam("fromDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime fromDate) { logger.debug("Request received!"); return "Received " + fromDate.toString(); }
Gradle依赖配置:
dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
调用接口时触发400错误,调用命令:
curl localhost:8080/transaction/search/another?fromDate=2022-05-09T01:30:00.000-5:00
错误响应:
{ "timestamp": "2023-02-23T21:44:12.191+00:00", "status": 400, "error": "Bad Request", "path": "/transaction/search/another" }
日志中的错误堆栈:
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.demo.RestController#searchTransactions(Optional, OffsetDateTime) o.s.beans.TypeConverterDelegate : Field [2022-05-09T01:30:00.000-5:00] isn't an enum value java.lang.NoSuchFieldException: 2022-05-09T01:30:00.000-5:00 at java.base/java.lang.Class.getField(Class.java:2117) ~[na:na] at org.springframework.beans.TypeConverterDelegate.attemptToConvertStringToEnum(TypeConverterDelegate.java:308) ~[spring-beans-6.0.5.jar:6.0.5] at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:215) ~[spring-beans-6.0.5.jar:6.0.5] at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73) ~[spring-beans-6.0.5.jar:6.0.5] at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:53) ~[spring-beans-6.0.5.jar:6.0.5] at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:729) ~[spring-context-6.0.5.jar:6.0.5] ....
注:将参数改为LocalDateTime并去掉请求中的偏移量后,接口可正常运行。
已尝试的无效解决方案
- 自定义ObjectMapper配置类
@Configuration public class JsonConfiguration { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule()) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); @Bean @Primary public static ObjectMapper getObjectMapper() { return OBJECT_MAPPER; } }
- 继承WebMvcConfigurationSupport添加自定义转换服务
@Bean @Override public FormattingConversionService mvcConversionService() { DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar(); dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd")); dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")); dateTimeRegistrar.registerFormatters(conversionService); DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar(); dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd")); dateRegistrar.registerFormatters(conversionService); return conversionService; }
- 配置Jackson2ObjectMapperBuilderCustomizer
@Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { return builder -> { // formatter DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // deserializers builder.deserializers(new OffsetDateTimeDeserializer()); // serializers builder.serializers(new OffsetDateTimeSerializer()); }; }
备选思路
如果上述方案均无效,考虑将参数类型改为String,在方法内部手动验证并转换为OffsetDateTime。
内容的提问来源于stack exchange,提问作者Sannu
相关产品推荐
相关产品推荐

