Spring Boot OpenAPI3如何让日期字段在Swagger中显示为yyyyMMdd格式
问题描述
请求模型中定义了如下字段:
@NotNull @Schema(example = "19680228", type = "String", format = "yyyyMMdd", pattern = "([0-9]{4})(?:[0-9]{2})([0-9]{2})", required = true, nullable = false) @JsonDeserialize(using = CustomDateDeserializer.class) private OffsetDateTime birthDate;
- 字段约束:
birthDate字段为OffsetDateTime类型,但接口入参仅支持yyyyMMdd格式的日期部分,该需求为硬性要求不可变更,目前已通过自定义CustomDateDeserializer完成反序列化逻辑处理,接口功能运行正常。 - 配置依据:根据OpenAPI规范,原生支持ISO8601规范的
date和date-time类型,使用内置类型时无需配置pattern属性,直接设置对应type即可;若因遗留系统兼容等限制需要使用非标准日期格式,需将type设为String,format指定实际使用的日期格式,同时配置正则表达式pattern做格式校验,上述@Schema注解配置完全符合该规则。 - 异常表现:将生成的.yaml文件导入Swagger在线编辑器后,请求模型与Controller接口中生成的
birthDate字段格式错误,配置的example示例值未生效:模型中该字段的format仍被自动识别为OffsetDateTime对应的默认日期时间格式,完全没有展示配置的示例值,Controller层的接口参数展示也存在同样的问题。 - 运行环境:Spring Boot应用集成OpenAPI/Swagger 3版本,需要实现Swagger文档中的该日期字段正确展示为
yyyyMMdd格式,在Swagger编辑器中正确显示19720226这类符合要求的示例值。
解决方案
问题根源是springdoc-openapi(Spring Boot生态下Swagger3的官方实现)默认会根据字段的Java类型自动映射Schema规则,优先级高于@Schema注解中手动配置的type、format、example属性。即使手动声明类型为String,框架检测到字段是OffsetDateTime类型时,仍会强制将Schema类型覆盖为默认的date-time格式,导致手动配置不生效。
按以下步骤配置即可解决:
- 第一步:修改字段上的
@Schema注解,增加implementation = String.class属性,强制指定Schema的实现类型为字符串,跳过框架对Java时间类型的自动映射逻辑。同时注意OpenAPI规范中类型名为小写,将原注解中大写的type = "String"改为type = "string",修正后的注解代码如下:
@NotNull @Schema( implementation = String.class, example = "19680228", type = "string", format = "yyyyMMdd", pattern = "^[0-9]{8}$", required = true, nullable = false, description = "出生日期,格式为yyyyMMdd" ) @JsonDeserialize(using = CustomDateDeserializer.class) @JsonFormat(pattern = "yyyyMMdd") private OffsetDateTime birthDate;
注意:正则
pattern建议调整为^[0-9]{8}$,原正则存在分组捕获逻辑,仅做格式校验时不需要额外分组,首尾加锚点可以避免非法长度字符串绕过校验。
- 第二步(可选,适用于多字段全局配置场景):如果项目中存在多个同规则的非标准格式日期字段,不需要每个字段重复写注解,直接注册OpenAPI自定义配置类,全局替换对应字段的Schema生成规则即可:
@Configuration public class OpenApiConfig { @Bean public OpenApiCustomiser openApiCustomiser() { return openApi -> openApi.getComponents().getSchemas().forEach((schemaName, schema) -> { Map<String, Schema> properties = schema.getProperties(); if (properties == null) { return; } properties.forEach((propName, propSchema) -> { // 匹配所有需要按yyyyMMdd格式展示的OffsetDateTime字段,可根据实际注解标记或字段名规则调整判断逻辑 if (propSchema instanceof DateTimeSchema && propName.endsWith("Date") && propName.startsWith("birth")) { properties.replace(propName, new StringSchema() .example("19720226") .format("yyyyMMdd") .pattern("^[0-9]{8}$") .required(true) .nullable(false) .description("出生日期,格式为yyyyMMdd") ); } }); }); } }
- 第三步:重启应用重新生成OpenAPI文档,对应字段生成的YAML片段如下,导入Swagger编辑器即可正确展示
yyyyMMdd格式和配置的示例值:
birthDate: type: string format: yyyyMMdd pattern: "^[0-9]{8}$" example: "19680228" required: true nullable: false
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

