OpenAPIスキーマ設定チートシート:nullable・enum・共通化まで
はじめに
OpenAPIでAPI仕様を書いていると「nullを許可したい」「選択肢を限定したい」「404レスポンスを毎回書くのが面倒」といった場面によく出会います。
この記事ではスキーマの主要な設定とよく使うパターンをまとめます。基本的な書き方は「OpenAPI入門:YAML仕様の書き方からSwagger UIで確認するまで」を参照してください。
型(type)一覧
| type | 説明 | 主なformat |
|---|---|---|
string |
文字列 | date / date-time / email / uuid / password / byte / binary |
integer |
整数 | int32 / int64 |
number |
小数を含む数値 | float / double |
boolean |
true / false | — |
array |
配列 | — |
object |
オブジェクト | — |
properties: name: type: string age: type: integer format: int32 score: type: number format: float is_active: type: boolean created_at: type: string format: date-time birth_date: type: string format: date email: type: string format: email token: type: string format: uuid
nullable(null許可)
OpenAPI 3.0と3.1で書き方が異なります。
OpenAPI 3.0の書き方
properties: deleted_at: type: string format: date-time nullable: true
OpenAPI 3.1の書き方(nullable は廃止され type にnullを含める)
properties: deleted_at: type: [string, "null"] format: date-time
どちらのバージョンを使っているかは openapi: の宣言で確認してください。
openapi: 3.1.0 # 3.0.x なら nullable: true を使う
enum(選択肢の限定)
プロパティの値を特定の値のみに制限します。
properties: status: type: string enum: - draft - published - archived role: type: string enum: - admin - editor - viewer
enumはnullableと組み合わせられます。
# OpenAPI 3.1 properties: status: type: [string, "null"] enum: - draft - published - archived - null
required・default・example
required:必須プロパティを指定する
components: schemas: User: type: object required: - id - name - email properties: id: type: integer name: type: string email: type: string bio: type: string # required に含まれていないので任意
default:値が省略されたときのデフォルト値
properties: per_page: type: integer default: 20 is_active: type: boolean default: true
example:Swagger UIで表示されるサンプル値
properties: name: type: string example: 田中太郎 email: type: string format: email example: tanaka@example.com
数値・文字列のバリデーション
数値の範囲
properties: age: type: integer minimum: 0 maximum: 150 score: type: number minimum: 0.0 maximum: 100.0 exclusiveMaximum: true # 100.0 は含まない
文字列の長さ
properties: username: type: string minLength: 3 maxLength: 50 password: type: string minLength: 8
正規表現パターン
properties: postal_code: type: string pattern: '^\d{3}-\d{4}$' example: 100-0001 phone: type: string pattern: '^\d{10,11}$'
配列の要素数
properties: tags: type: array items: type: string minItems: 1 maxItems: 10 uniqueItems: true # 重複を禁止
共通化(components)
同じ定義を複数のエンドポイントで使い回すときは components にまとめて $ref で参照します。
components/schemas:スキーマの共通化
components: schemas: User: type: object required: - id - name properties: id: type: integer example: 1 name: type: string example: 田中太郎 ErrorResponse: type: object required: - code - message properties: code: type: string example: not_found message: type: string example: リソースが見つかりません
components/responses:レスポンスの共通化
404・401・422など毎回書くレスポンスをまとめます。
components: responses: NotFound: description: リソースが見つからない content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Unauthorized: description: 認証が必要 content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' UnprocessableEntity: description: バリデーションエラー content: application/json: schema: type: object properties: errors: type: array items: type: object properties: field: type: string example: email message: type: string example: は不正な値です
各エンドポイントで $ref を使って参照します。
paths: /users/{id}: get: summary: ユーザーを1件取得する parameters: - $ref: '#/components/parameters/UserId' responses: '200': description: 成功 content: application/json: schema: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /users: post: summary: ユーザーを作成する responses: '201': description: 作成成功 content: application/json: schema: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/UnprocessableEntity'
components/parameters:パラメータの共通化
パスパラメータやクエリパラメータも共通化できます。
components: parameters: UserId: name: id in: path required: true description: ユーザーID schema: type: integer PageNumber: name: page in: query required: false schema: type: integer default: 1 PerPage: name: per_page in: query required: false schema: type: integer default: 20 maximum: 100
paths: /users: get: parameters: - $ref: '#/components/parameters/PageNumber' - $ref: '#/components/parameters/PerPage'
oneOf / anyOf / allOf
複数のスキーマを組み合わせるときに使います。
allOf:すべてのスキーマを満たす(継承に使う)
components: schemas: Timestamps: type: object properties: created_at: type: string format: date-time updated_at: type: string format: date-time User: allOf: - $ref: '#/components/schemas/Timestamps' - type: object required: - id - name properties: id: type: integer name: type: string
oneOf:いずれか1つのスキーマにマッチする(Union型)
components: schemas: PaymentMethod: oneOf: - $ref: '#/components/schemas/CreditCard' - $ref: '#/components/schemas/BankTransfer' discriminator: propertyName: type
anyOf:1つ以上のスキーマにマッチする
properties: contact: anyOf: - type: object properties: email: type: string format: email - type: object properties: phone: type: string
まとめ
| キーワード | 用途 |
|---|---|
type / format |
データ型と形式を指定する |
nullable: true / type: [string, "null"] |
null許可(3.0 / 3.1) |
enum |
選択肢を限定する |
required |
必須プロパティを指定する |
default |
デフォルト値を指定する |
minimum / maximum |
数値の範囲を指定する |
minLength / maxLength |
文字列の長さを指定する |
pattern |
正規表現でフォーマットを制限する |
example |
サンプル値を指定する |
$ref |
共通定義を参照する |
allOf |
スキーマを継承・合成する |
oneOf |
いずれか1つのスキーマにマッチさせる |
OpenAPIからTypeScriptの型定義とfetchクライアントを自動生成する方法は「OpenAPIからTypeScript型定義とfetchクライアントを自動生成する」を参照してください。
OpenAPIを使ったRailsのコントローラー実装は「RailsでOpenAPIを使ったコントローラー作成入門」を参照してください。