Spring Doc 2.2.0与WebMvcConfigurer:时间戳及Swagger UI渲染问题
环境
- Spring Boot 3.0.4
- Spring Doc 2.2.0
初始问题
实体类中OffsetDateTime类型的eventStart字段,接口返回时被序列化为时间戳格式(如1647302400.000000000),不符合预期的ISO-8601格式(如2022-03-15T00:00:00Z)。
临时解决尝试
为修正时间序列化格式,实现了WebMvcConfigurer配置类,添加自定义MappingJackson2HttpMessageConverter,禁用时间戳序列化特性并注册JavaTimeModule:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new MappingJackson2HttpMessageConverter(objectMapper())); } private ObjectMapper objectMapper() { JavaTimeModule module = new JavaTimeModule(); return new ObjectMapper() .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .registerModule(module) .registerModule(new JavaTimeModule()); } }
调整后eventStart字段确实能输出预期的ISO格式,但引出了新问题。
新问题
Swagger UI无法正常渲染,提示:提供的定义未指定有效的版本字段,要求指定swagger: "2.0"或openapi: 3.x.y版本。当前application.yml配置如下:
springdoc: swagger-ui: # custom path for swagger-ui path: /${spring.application.name}.html api-docs: #custom path for api docs path: /docs/api version: OPENAPI_3_1 paths-to-match: /** show-actuator: true
最终解决方案
问题根源在于@EnableWebMvc注解和自定义消息转换器的方式:@EnableWebMvc会完全接管Spring MVC的配置,覆盖了Spring Doc默认的消息转换器,导致OpenAPI文档的序列化逻辑被破坏。
修正方案1:修改WebMvc配置类
移除@EnableWebMvc注解,通过extendMessageConverters方法修改已有的Jackson转换器,而非添加新的转换器:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { for (HttpMessageConverter<?> converter : converters) { if (converter instanceof MappingJackson2HttpMessageConverter jacksonConverter) { ObjectMapper objectMapper = jacksonConverter.getObjectMapper(); // 禁用时间戳序列化 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 注册JavaTimeModule(避免重复注册) if (!objectMapper.getRegisteredModuleIds().contains(JavaTimeModule.class.getName())) { objectMapper.registerModule(new JavaTimeModule()); } break; } } } }
修正方案2:直接定义全局ObjectMapper Bean
更简洁的方式是直接配置全局的ObjectMapper Bean,Spring Boot会自动将其应用到默认的消息转换器中,无需实现WebMvcConfigurer:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper() .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .registerModule(new JavaTimeModule()); } }
两种方案都能保证OffsetDateTime字段输出ISO格式,同时保留Spring Doc的默认配置,Swagger UI即可正常渲染OpenAPI 3.1文档。
内容的提问来源于stack exchange,提问作者B Randall

