使用 OpenAPI 生成器映射日期類型
一、概述
在本教程中,我們將了解如何使用 OpenAPI 映射日期。我們將學習如何處理各種日期格式。
兩個不同的 Maven 插件允許從 OpenAPI 規範生成代碼: swagger-codegen
和openapi-generator
。我們將討論如何同時使用它們。
2. 示例設置
首先,讓我們舉個例子。我們將編寫我們的初始 YAML 文件和 Maven 插件的基本配置。
2.1.基礎 YAML 文件
我們將使用 YAML 文件來描述我們的 API。請注意,我們將使用 OpenAPI 規範的第三版。
我們需要為文件添加標題和版本以符合規範。此外,我們會將paths
部分留空。然而,在components
部分,我們將定義一個Event
對象,它目前只有一個屬性,即它的組織者:
openapi: 3.0.0
info:
title: an example api with dates
version: 0.1.0
paths:
components:
schemas:
Event:
type: object
properties:
organizer:
type: string
2.2. swagger-codegen
插件配置
可以在Maven Central Repository中找到最新版本的swagger-codegen
插件。讓我們從插件的基本配置開始:
<plugin>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.34</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
類是根據 OpenAPI 規範生成的,具有構造函數、getter 和 setter。它的equals()
、 hashcode()
和toString()
方法也被覆蓋。
2.3. openapi-generator
插件配置
同樣,最新版本的openapi-generator
插件在Maven Central Repository中可用。現在讓我們為它做基本配置:
<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>
根據 OpenAPI 規範,我們的 YAML 文件中有一個空paths
部分是可以的。但是, openapi-generator
默認會拒絕它。因此,我們將skipValidateSpec
標誌設置為true.
我們還在選項列表中將openApiNullable
屬性設置為false
,否則插件會要求我們向jackson-databing-nullable
添加一個我們不需要的依賴項。
我們還將interfaceOnly
設置為true,
主要是為了避免生成不必要的 Spring Boot 集成測試。
在這種情況下,運行compile
Maven 階段也會生成具有所有方法的Event
類。
3. OpenAPI 標準日期映射
OpenAPI 定義了幾種基本數據類型: string
就是其中之一。在string
數據類型中,OpenAPI 定義了兩種默認格式來處理日期: date
和date-time
。
3.1. date
date
格式是指RFC 3339 第 5.6 節定義的完整日期表示法。例如, 2023-02-08
就是這樣一個日期。
現在讓我們將date
格式的startDate
屬性添加到我們的Event
定義中:
startDate:
type: string
format: date
我們不需要更新 Maven 插件的配置。讓我們再次生成Event
類。我們可以看到生成的文件中出現了一個新的屬性:
@JsonProperty("startDate")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate startDate;
這兩個插件之間的主要區別在於swagger-codegen
不使用@DateTimeFormat
註釋startDate
屬性。這兩個插件還以相同的方式創建關聯的 getter、setter 和構造函數。
正如我們所見,生成器的默認行為是使用LocalDate
類作為date
格式。
3.2. date-time
date-time
格式是指 RFC 3339 第 5.6 節定義的日期時間表示法。例如, 2023-02-08T18:04:28Z
匹配此格式。
現在讓我們將date-time
格式的endDate
屬性添加到我們的事件中:
endDate:
type: string
format: date-time
再一次,我們不需要修改任何插件的配置。當我們再次生成 Event 類時,會出現一個新屬性:
@JsonProperty("endDate")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private OffsetDateTime endDate;
我們對date
格式所做的評論仍然有效:與openapi-generator
相反, swagger-codegen
不使用@DateTimeFormat
註釋該屬性。此外,插件創建關聯的 getter、setter 和構造函數。
我們可以看到生成器默認使用OffsetDateTime
類來表示date-time
格式。
4.使用其他標準日期類
我們現在將強制插件為每種格式使用特定的類,而不是生成默認類。
讓我們編輯swagger-codegen
Maven 插件配置:
<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>
讓我們仔細看看新行:
- 我們使用帶有
custom
值的dateLibrary
選項:這意味著我們將定義我們自己的日期類而不是使用標準類 - 在
importMappings
部分,我們告訴插件導入Instant
和Date
類並告訴它在哪裡查找它們 -
typeMappings
部分是所有魔法發生的地方:我們告訴插件使用Instant
來處理date-time
格式,並使用Date
來處理date
格式
對於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>
現在讓我們生成文件並查看它們:
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;
該插件確實用Date
對象替換了date
格式,用 Instant 替換了date-time
格式Instant.
和以前一樣,這兩個插件之間的唯一區別是swagger-codegen
不使用@DateTimeFormat
註釋屬性。
最後但並非最不重要的一點是,請注意插件沒有任何驗證。例如,我們可以使用java.lang.Math
類來模擬日期格式,代碼仍然可以成功生成。
5.使用自定義日期模式
我們現在將討論最後一種可能性。如果出於某種原因,我們真的不能依賴任何標準的日期 API,我們總是可以使用String
來處理我們的日期。在這種情況下,我們需要定義我們希望字符串遵循的驗證模式。
例如,讓我們將ticketSales
日期添加到我們的Event
對象規範中。此ticketSales
將被格式化為DD-MM-YYYY
,例如18-07-2024
:
ticketSales:
type: string
description: Beginning of the ticket sales
example: "01-01-2023"
pattern: "[0-9]{2}-[0-9]{2}-[0-9]{4}"
如我們所見,我們定義了ticketSales
必須匹配的正則表達式。請注意,此模式無法區分DD-MM-YYYY
和MM-DD-YYYY
。此外,我們還為此字段添加了描述和示例:由於我們不以標準方式處理日期,因此洞察力似乎很有幫助。
我們不需要對插件的配置進行任何更改。讓我們用openapi-generator
生成Event
類:
@JsonProperty("ticketSales")
private String ticketSales;
(...)
/**
* Beginning of the ticket sales
* @return ticketSales
*/
@Pattern(regexp = "[0-9]{2}-[0-9]{2}-[0-9]{4}")
@Schema(name = "ticketSales", example = "01-01-2023", description = "Beginning of the ticket sales", required = false)
public String getTicketSales() {
return ticketSales;
}
正如我們所看到的,getter 是用定義的Pattern
註釋的。因此,我們需要向javax.validation
添加依賴項以使其工作:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
swagger-codegen
插件生成非常相似的代碼。
六,結論
在本文中,我們已經看到swagger-codegen
和openapi-generator
Maven 插件都提供了用於日期和日期時間處理的內置格式。如果我們更喜歡使用其他標準的 Java 日期 API,我們可以覆蓋插件的配置。當我們真的不能使用任何日期 API 時,我們總是可以將日期存儲為String
並手動指定驗證模式。
與往常一樣,代碼在 GitHub 上可用。