OpenAPIスキーマ設定チートシート:nullable・enum・共通化まで

スポンサーリンク

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を使ったコントローラー作成入門」を参照してください。