1. 概述

本文将探讨如何在 OpenAPI 中处理日期映射,包括各种日期格式的处理方法。我们将使用两个主流 Maven 插件:swagger-codegenopenapi-generator,它们都能根据 OpenAPI 规范生成代码。

2. 示例搭建

首先搭建基础示例,包括初始 YAML 文件和 Maven 插件配置。

2.1 基础 YAML 文件

使用 YAML 文件描述 API(基于 OpenAPI 3.0 规范):

openapi: 3.0.0
info:
  title: 日期处理示例 API
  version: 0.1.0
paths:
components:
  schemas:
    Event:
      type: object
      properties:
        organizer:
          type: string

2.2 swagger-codegen 插件配置

基础配置如下(最新版本可在 Maven 中央仓库 查找):

<plugin>
    <groupId>io.swagger.codegen.v3</groupId>
    <artifactId>swagger-codegen-maven-plugin</artifactId>
    <version>3.0.52</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>${project.basedir}/src/main/resources/static/event.yaml</inputSpec>
                <language>spring</language>
                <configOptions>
                    <java8>true</java8>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

执行生成命令:

mvn clean compile

生成的 Event 类包含构造器、getter/setter 以及重写的 equals()hashcode()toString() 方法。

2.3 openapi-generator 插件配置

基础配置如下(最新版本可在 Maven 中央仓库 查找):

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>6.2.1</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <skipValidateSpec>true</skipValidateSpec>
                <inputSpec>${project.basedir}/src/main/resources/static/event.yaml</inputSpec>
                <generatorName>spring</generatorName>
                <configOptions>
                    <java8>true</java8>
                    <openApiNullable>false</openApiNullable>
                    <interfaceOnly>true</interfaceOnly>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

⚠️ 关键配置说明

  • skipValidateSpec=true:跳过空 paths 验证
  • openApiNullable=false:避免引入 jackson-databing-nullable 依赖
  • interfaceOnly=true:不生成 Spring Boot 集成测试

执行 mvn compile 同样生成完整的 Event 类。

3. OpenAPI 标准日期映射

OpenAPI 在 string 类型中定义了两种日期格式:datedate-time

3.1 date 格式

符合 RFC 3339 全日期格式(如 2023-02-08)。

Event 中添加 startDate 属性:

startDate:
  type: string
  format: date

生成代码:

@JsonProperty("startDate")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate startDate;

关键点

  • 默认使用 LocalDate
  • openapi-generator 会添加 @DateTimeFormat 注解
  • swagger-codegen 不会添加该注解

3.2 date-time 格式

符合 RFC 3339 日期时间格式(如 2023-02-08T18:04:28Z)。

Event 中添加 endDate 属性:

endDate:
  type: string
  format: date-time

生成代码:

@JsonProperty("endDate")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private OffsetDateTime endDate;

关键点

  • 默认使用 OffsetDateTime
  • 注解行为与 date 格式一致

4. 使用其他标准日期类

通过配置强制插件使用指定日期类。

4.1 swagger-codegen 配置

<configuration>
    <inputSpec>${project.basedir}/src/main/resources/static/event.yaml</inputSpec>
    <language>spring</language>
    <configOptions>
        <java8>true</java8>
        <dateLibrary>custom</dateLibrary>
    </configOptions>
    <typeMappings>
        <typeMapping>DateTime=Instant</typeMapping>
        <typeMapping>Date=Date</typeMapping>
    </typeMappings>
    <importMappings>
        <importMapping>Instant=java.time.Instant</importMapping>
        <importMapping>Date=java.util.Date</importMapping>
    </importMappings>
</configuration>

4.2 openapi-generator 配置

<configuration>
    <skipValidateSpec>true</skipValidateSpec>
    <inputSpec>${project.basedir}/src/main/resources/static/event.yaml</inputSpec>
    <generatorName>spring</generatorName>
    <configOptions>
        <java8>true</java8>
        <dateLibrary>custom</dateLibrary>
        <openApiNullable>false</openApiNullable>
        <interfaceOnly>true</interfaceOnly>
    </configOptions>
    <typeMappings>
        <typeMapping>DateTime=Instant</typeMapping>
        <typeMapping>Date=Date</typeMapping>
    </typeMappings>
    <importMappings>
        <importMapping>Instant=java.time.Instant</importMapping>
        <importMapping>Date=java.util.Date</importMapping>
    </importMappings>
</configuration>

4.3 生成结果

import java.time.Instant;
import java.util.Date;

(...)
    @JsonProperty("startDate")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private Date startDate;

    @JsonProperty("endDate")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private Instant endDate;

⚠️ 注意事项

  • 插件不会验证类型映射的合理性(比如用 Math 类处理日期也能生成)
  • swagger-codegen 仍不会添加 @DateTimeFormat 注解

5. 使用自定义日期模式

当标准日期类无法满足需求时,可用 String 配合正则验证。

Event 中添加 ticketSales 属性(格式 DD-MM-YYYY):

ticketSales:
  type: string
  description: 票务销售开始日期
  example: "01-01-2023"
  pattern: "[0-9]{2}-[0-9]{2}-[0-9]{4}"

生成代码(以 openapi-generator 为例):

@JsonProperty("ticketSales")
private String ticketSales;

(...)

/**
 * 票务销售开始日期
 * @return ticketSales
*/
@Pattern(regexp = "[0-9]{2}-[0-9]{2}-[0-9]{4}") 
@Schema(name = "ticketSales", example = "01-01-2023", description = "票务销售开始日期", required = false)
public String getTicketSales() {
  return ticketSales;
}

关键点

  • 需添加 javax.validation 依赖:
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>2.0.1.Final</version>
    </dependency>
    
  • 正则无法区分 DD-MM-YYYYMM-DD-YYYY
  • 建议添加 descriptionexample 提高可读性

6. 总结

本文对比了两个主流 OpenAPI 生成器的日期处理能力:

  1. 内置支持:默认使用 LocalDatedate)和 OffsetDateTimedate-time
  2. 自定义映射:通过 typeMappings 强制使用其他日期类(如 Instant/Date
  3. 兜底方案:使用 String + 正则验证处理特殊格式

代码示例可在 GitHub 获取。


原始标题:Map Date Types With OpenAPI Generator | Baeldung