OpenAPI Specificationの記載ルールについて

## 概要

- OpenAPI Specificationの記載ルールの基本的な部分をまとめる。
- 必須のルートオブジェクト部分だけ深堀りして記載する。

## OpenAPIドキュメントについて

- OpenAPIドキュメントの記載はプロジェクトによって固有のルールがあるっぽいので郷に入っては郷に従うほうがいいと思う。
- OpenAPIドキュメントそのものも、「1リクエストにつき1ファイル」のこともあれば「関連するリクエストは1ファイルにまとめる（ユーザー系は1ファイルにまとめる）」等のルールが有ると思う

## ルートオブジェクトについて

- `openapi`, `info`, `paths`のルートオブジェクトは必須となる。とりあえずこの3オブジェクトが記載されていればOpenAPIの仕様書として成り立つ。
- 記載のセオリーとしてはできるだけ`components`オブジェクトに`paths`オブジェクトと`security`オブジェクトで使用する内容をなるべく記載し、適宜コンポーネントを呼び出すほうが使いまわしが効いていいのかもしれない。
- もちろん他のオブジェクトも非常に大切だが、とりあえず必須のオブジェクト+`components`と`security`オブジェクトの記載方法がわかっていれば大丈夫そう。

| ルートオブジェクト名 | 内容 | 必須可否 |  |
| --- | --- | --- | --- |
| openapi | 記載するOpenAPIのバージョンを記載 | 必須 |  |
| info | 記載しようとしているAPI仕様書のメタデータを記載 | 必須 |  |
| servers | 記載しようとしているAPIがとのような環境で提供されるのかを記載 |  |  |
| tags | 記載しようとしているAPIを分類するためのタグを定義 |  |  |
| paths | 記載しようとしているAPIの最も大切な部分<br>どのURLにリクエスト送ってどんな内容が帰るのか等 | 必須 | かなり重要だし結構複雑<br>OpenAPIのメインと行っても過言ではない |
| security | 記載しようとしているAPIのセキュリティー要件を定義 |  |  |
| components | OpenAPI内で使用するオブジェクトを定義してコンポーネント化し、使い回せるようにする |  |  |

## openapiオブジェクトについて

- openapiオブジェクトでは当該のOpenAPIドキュメントのバージョンを記載する。
- バージョン情報は下記で確認できる。
    - [https://github.com/OAI/OpenAPI-Specification/tree/main/versions](https://github.com/OAI/OpenAPI-Specification/tree/main/versions)
- OpenAPIのバージョンは下記の様に記載する。

    ```openapi.yaml
    openapi: "3.0.3"
    ```

## infoオブジェクトについて

- 当該のOpenAPIドキュメントのメタデータ（概要や詳細）などを記載する。

    | オブジェクト名 | 内容 | 必須可否 | 備考 |
    | --- | --- | --- | --- |
    | title | OpenAPIドキュメントそのもののタイトルを定義 | 必須 | 例えば「ユーザー系APIドキュメント」とか |
    | description | OpenAPIドキュメントの詳細内容 |  | Markdownで記載する事ができる |
    | termsOfService | サービス利用規約のURL |  | APIを公開する際に必要な情報 |
    | contact | 連絡先情報 |  | APIを公開する際に必要な情報 |
    | license | ライセンス情報 |  | APIを公開する際に必要な情報<br>SPDXを参考に記載するとわかりやすい |
    | version | OpenAPIドキュメントそのもののバージョン |  | 今あなたが記載しているドキュメントそのものバージョン情報<br>OpenAPIのバージョン情報ではないので注意 |

- 必須部分（とopenapiルートオブジェクト）だけ記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"
    ```

## tagsオブジェクトについて

- pathsオブジェクトやその他のオブジェクトで分類分けに使用するタグを予めtagsオブジェクトで定義する事ができる。
- 例えばユーザー系APIに張る`users`タグを定義する場合は下記の様に指定する。（tagsは配列で定義する）

    | キー名 | 内容 | 備考 |
    | --- | --- | --- |
    | name | タグ名 | 例えば'"users"'等 |
    | description | タグの説明 |  |

## pathsオブジェクトについて

- pathsオブジェクトはOpenAPIドキュメントで記載されるAPI情報のまさにメイン箇所である。
- 情報が多くなるためpathsオブジェクトの階層も深くなる。そのためpathsオブジェクトの説明のみ、階層に分けて実施する。
- 当該のリクエストのURLを指定する。

    | オブジェクト名 | 内容 | 必須可否 | 備考 |
    | --- | --- | --- | --- |    
    | 当該APIのアクセスURL | アクセスURLを`""`で囲って記載する | 必須 | 例えば'"/login"'等 |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"
    ```

## paths → 当該APIのアクセスURLオブジェクトについて

- paths直下の当該APIのアクセスURLオブジェクトには当該のリクエストのHTTPメソッドオブジェクトが配置される。

    | オブジェクト名 | 内容 | 必須可否 | 備考 |
    | --- | --- | --- | --- |    
    | 当該APIのHTTPメソッド | HTTPメソッドを記載 | 必須 | 小文字で当該APIのHTTPメソッドを定義 |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login":
        post:
    ```

## paths → 当該APIのアクセスURL → HTTPメソッドオブジェクトについて

- paths直下、当該APIのアクセスURL直下、HTTPメソッドオブジェクトには下記の内容のオブジェクトが配置される。

    | オブジェクト名 | 内容 | 必須可否 | 備考 |
    | --- | --- | --- | --- |    
    | summary | 当該APIのタイトル |  |  |
    | description | 当該APIの説明 |  | Markdownで記載可能 |
    | tags | タグの定義 |  | 任意のタグをこちらで定義する or<br>componentルートオブジェクト内で定義したタグを呼び出す |
    | deprecated | 当該APIが廃止されているか否か |  | true → 廃止されている<br>false → 廃止されていない |
    | parameter | リクエストパラメーターの内容 |  |  |
    | requestBody | リクエストボディーの内容 |  | リクエストボディーで値を渡す場合に記載 |
    | response | レスポンスの内容 |  | ステータスコードごとに記載する |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameter:
          requestBody:
          response:
    ```

## paths → 当該APIのアクセスURL → HTTP →　parametersメソッドオブジェクトについて

- paths直下、当該APIのアクセスURL直下、HTTP直下、parametersメソッドオブジェクトには下記の内容のキー（配列）が配置される。

    | キー名 | 内容 | 備考 |
    | --- | --- | --- |    
    | name | 渡される値のキー | parametersオブジェクトを定義する場合必須 |
    | in | パラメーターの場所 | query, header, path, cookieの中から選んで記載 |
    | reequired | 必須か否か | true → 必須<br>false → 必須ではない<br>pathパラメーターの場合、trueにしないとURLが成り立たないので注意 |
    | schema | 渡される値の型を定義 | オブジェクトで定義 |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema: { type: string }
          requestBody:
          response:
    ```

## paths → 当該APIのアクセスURL → HTTP →　requestBodyメソッドオブジェクトについて

- paths直下、当該APIのアクセスURL直下、HTTP直下、requestBodyメソッドオブジェクトには下記の内容のキー（配列）が配置される。

    | オブジェクト名 | 内容 | 備考 |
    | --- | --- | --- |    
    | description | リクエストボディーの説明 |  |
    | required | 必須か否か | true → 必須<br>false → 必須ではない |
    | content | リクエストボディーの内容 |  |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema: { type: string }
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
          response:
    ```

## paths → 当該APIのアクセスURL → HTTP →　requestBody → contentメソッドオブジェクトについて（jsonでオブジェクトの場合）

- paths直下、当該APIのアクセスURL直下、HTTP直下、requestBody直下、contentメソッドオブジェクトには下記の内容のキー（配列）が配置される。

    | オブジェクト名 | 内容 | 備考 |
    | --- | --- | --- |    
    | メディアタイプ | 当該リクエストボディーのメディアタイプ | application/json |
    | メディアタイプ → schema | 当該リクエストボディーの情報 |  |
    | メディアタイプ → schema → type | 当該リクエストボディーの型 |  |
    | メディアタイプ → schema → properties | 当該リクエストボディーの型がobjectの場合 |  |
    | メディアタイプ → schema → properties → オブジェクトのキー名{オブジェクト} | データオブジェクト内部の型定義と例の記載 |  |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema: { type: string }
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema: 
                  type: object
                  properties: 
                    email: { type: string, example: "test@example.com" }
                    password: { type: string, example: "p@ssw0rd" }
          response:
    ```

## paths → 当該APIのアクセスURL → HTTP →　responseメソッドオブジェクトについて

- paths直下、当該APIのアクセスURL直下、HTTP直下、responseメソッドオブジェクトには下記の内容が配置される。

    | オブジェクト名 | 内容 | 備考 |
    | --- | --- | --- |
    | HTTPステータスコード | 想定されるレスポンスのHTTPステータスコード | 200や400などの個別指定から2XXや4XXといった200番台、400番台等のレスポンスの指定が可能 |
    | HTTPステータスコード → description | レスポンスの説明 |  |
    | HTTPステータスコード → content | レスポンスの内容 |  |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema: { type: string }
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema: 
                  type: object
                  properties: 
                    email: { type: string, example: "test@example.com" }
                    password: { type: string, example: "p@ssw0rd" }
          response:
            "2XX": 
              description: "成功処理"
              content:
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
    ```

## paths → 当該APIのアクセスURL → HTTP →　response →　contentメソッドオブジェクトについて

- paths直下、当該APIのアクセスURL直下、HTTP直下、response直下、contentメソッドオブジェクトには下記の内容が配置される。

    | オブジェクト名 | 内容 | 備考 |
    | --- | --- | --- |    
    | メディアタイプ | 当該レスポンスのメディアタイプ | application/json |
    | メディアタイプ → schema | 当該レスポンスの情報 |  |
    | メディアタイプ → schema → type | 当該レスポンスの型 |  |
    | メディアタイプ → schema → properties | 当該レスポンスの型がobjectの場合 |  |
    | メディアタイプ → schema → properties → オブジェクトのキー名{オブジェクト} | データオブジェクト内部の型定義と例の記載 |  |

- ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema: { type: string }
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema: 
                  type: object
                  properties: 
                    email: { type: string, example: "test@example.com" }
                    password: { type: string, example: "p@ssw0rd" }
          response:
            "2XX": 
              description: "成功処理"
              content:
                application/json:
                  schema:
                    type: object
                    properties: 
                      message: { type: string, example: "OK" }
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
                application/json:
                  schema:
                    type: object
                    properties: 
                      message: { type: string, example: "Client NG" }
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
                application/json:
                  schema:
                    type: object
                    properties: 
                      message: { type: string, example: "Server NG" }
    ```

## componentsオブジェクトについて

- コンポーネント化したい内容を分類ごとに名前を付けて下記の様に定義する。

    | オブジェクト名 | 内容 | 備考 |
    | --- | --- | --- |    
    | schemas | コンポーネント化するグループ名を記載 |  |
    | schemas → グループ名 | コンポーネントのそのものの定義 |  |

- ここまでの内容をcomponentsオブジェクトを用いて記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths:
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema: { type: string }
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema: 
                  type: object
                  properties: 
                    email: { type: string, example: "test@example.com" }
                    password: { type: string, example: "p@ssw0rd" }
          response:
            "2XX": 
              description: "成功処理"
              content:
                application/json:
                  schema:
                    type: object
                    properties: 
                      message: { type: string, example: "OK" }
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
                application/json:
                  schema:
                    type: object
                    properties: 
                      message: { type: string, example: "Client NG" }
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
                application/json:
                  schema:
                    type: object
                    properties: 
                      message: { type: string, example: "Server NG" }

    components:
      schemas:
        RequestHeader:
          type: string
        RequestBody: 
          type: object
          properties: 
            email: { type: string, example: "test@example.com" }
            password: { type: string, example: "p@ssw0rd" }
        OkResponse:
          type: object
          properties: 
            message: { type: string, example: "OK" }
        ClientNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Client NG" }
        ServerNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Server NG" }
    ```

- 更にここからcomponentsで定義した内容を各schemaで呼び出すと下記の様になる。（`$ref: "#/components/schemas/componentsで定義したグループ名"`でコンポーネントを呼び出す事ができる。）

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths: 
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema:
              $ref: "#/components/schemas/RequestHeader"
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema:
                  $ref: "#/components/schemas/RequestBody"
          responses:
            "2XX": 
              description: "成功処理"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/OkResponse"
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ClientNgResponse"
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ServerNgResponse"
    
    components:
      schemas:
        RequestHeader:
          type: string
        RequestBody: 
          type: object
          properties: 
            email: { type: string, example: "test@example.com" }
            password: { type: string, example: "p@ssw0rd" }
        OkResponse:
          type: object
          properties: 
            message: { type: string, example: "OK" }
        ClientNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Client NG" }
        ServerNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Server NG" }
    ```

## securityオブジェクトについて

- 当該APIのセキュリティー要件を定義する。
- まずcomponentsに定義を行い、そのコンポーネントを各pathsの記載で呼び出す。もしくはpathsに記載されているすべてのAPIに対してセキュリティー要件を設定し、不要なものを除外する。
- 今回はOAuth2.0のセキュリティー要件を記載してみる。
- 下記の様に記載する。（値は公式ドキュメントの値を設定していますが、各々のの環境にあった内容を記載してください。）

    | オブジェクト名 | 内容 |  必須可否 | 備考 |
    | --- | --- | --- | --- |
    | securitySchemas | コンポーネント化するセキュリティー要件のグループ名を記載 |  |  |
    | securitySchemas → グループ名 | セキュリティーそのものの定義 |  |  |
    | securitySchemas → グループ名 → type | セキュリティーのタイプを記載 |  | OAuthとかの認証の種類 |
    | securitySchemas → グループ名 → description | セキュリティーの説明を記載 |  |  |
    | securitySchemas → グループ名 → flows | OAuthのフローを指定 |  | OAuthのみ、複数存在する<br>こちらに記載[OAuth Flows Object](https://github.com/OAI/OpenApi-Specification/blob/main/versions/3.0.3.md#oauthFlowsObject) |
    | securitySchemas → グループ名 → flows → authorizationCode | OAuthの構成を記載 |  | OAuthのみ |
    | securitySchemas → グループ名 → flows → authorizationCode → authorizationUrl | 認証URL URL形式のみ受付 | 必須 |  OAuthのみ<br>こちらに記載[OAuth Flow Object](https://github.com/OAI/OpenApi-Specification/blob/main/versions/3.0.3.md#oauthFlowObject) |
    | securitySchemas → グループ名 → flows → authorizationCode → tokenUrl | トークンURL URL形式のみ受付 | 必須 |  OAuthのみ |
    | securitySchemas → グループ名 → flows → authorizationCode → refreshUrl | リフレッシュトークンURL URL形式のみ受付 | |  OAuthのみ |
    | securitySchemas → グループ名 → flows → authorizationCode → scopes | スコープ名と説明の記載 | 必須 | OAuth2.0のみ |

- これまでの記載とセキュリティーの内容をcomponentsに記載すると下記の様になる。

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths: 
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema:
              $ref: "#/components/schemas/RequestHeader"
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema:
                  $ref: "#/components/schemas/RequestBody"
          responses:
            "2XX": 
              description: "成功処理"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/OkResponse"
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ClientNgResponse"
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ServerNgResponse"
    
    components:
      schemas:
        RequestHeader:
          type: string
        RequestBody: 
          type: object
          properties: 
            email: { type: string, example: "test@example.com" }
            password: { type: string, example: "p@ssw0rd" }
        OkResponse:
          type: object
          properties: 
            message: { type: string, example: "OK" }
        ClientNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Client NG" }
        ServerNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Server NG" }
      securitySchemes:
        oauth:
          type: oauth2
          description: "OAuth2.0認証"
          flows:
            authorizationCode:
              authorizationUrl: https://example.com/api/oauth/dialog
              tokenUrl: https://example.com/api/oauth/token
              scopes:
                write:pets: modify pets in your account
                read:pets: read your pets
    ```

- pathsオブジェクト個々にセキュリティーを指定する場合、下記の様になる。（pathsの中のAPIオブジェクトにsecurityオブジェクトを追加して指定、scopeが必要な場合は`[]`の中にスコープ名を記載する。）

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths: 
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema:
              $ref: "#/components/schemas/RequestHeader"
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema:
                  $ref: "#/components/schemas/RequestBody"
          responses:
            "2XX": 
              description: "成功処理"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/OkResponse"
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ClientNgResponse"
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ServerNgResponse"
          security:
          - oauth2: []
    
    components:
      schemas:
        RequestHeader:
          type: string
        RequestBody: 
          type: object
          properties: 
            email: { type: string, example: "test@example.com" }
            password: { type: string, example: "p@ssw0rd" }
        OkResponse:
          type: object
          properties: 
            message: { type: string, example: "OK" }
        ClientNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Client NG" }
        ServerNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Server NG" }
      securitySchemes:
        oauth:
          type: oauth2
          description: "OAuth2.0認証"
          flows:
            authorizationCode:
              authorizationUrl: https://example.com/api/oauth/dialog
              tokenUrl: https://example.com/api/oauth/token
              scopes:
                write:pets: modify pets in your account
                read:pets: read your pets
    ```

- pathsオブジェクトすべてににセキュリティーを指定する場合、下記の様になる。（securityルートオブジェクトでセキュリティーコンポーネントを呼び出す。解除したいAPIだけpathsのsecurityオブジェクトに空の配列を指定する。 → `security: []`）

    ```openapi.yaml
    openapi: "3.0.3"

    info:
      title: "ユーザー系API"
      version: "1.0.0"

    tags:
    - name: "users"
      description: "ユーザー系API"

    paths: 
      "/login/{userId}":
        post:
          summary: "ログイン"
          description : |
            - 認証を行いトークンを発行
          tags: ["users"]
          deprecated: false
          parameters:
          - name: "userId"
            in: path
            required: true
            schema:
              $ref: "#/components/schemas/RequestHeader"
          requestBody:
            description: "ユーザー認証情報"
            required: true
            content: 
              application/json:
                schema:
                  $ref: "#/components/schemas/RequestBody"
          responses:
            "2XX": 
              description: "成功処理"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/OkResponse"
            "4XX": 
              description: "失敗処理（クライアントエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ClientNgResponse"
            "5XX": 
              description: "失敗処理（サーバーエラー）"
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ServerNgResponse"

    security:
      - oauth2: []
    
    components:
      schemas:
        RequestHeader:
          type: string
        RequestBody: 
          type: object
          properties: 
            email: { type: string, example: "test@example.com" }
            password: { type: string, example: "p@ssw0rd" }
        OkResponse:
          type: object
          properties: 
            message: { type: string, example: "OK" }
        ClientNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Client NG" }
        ServerNgResponse:
          type: object
          properties: 
            message: { type: string, example: "Server NG" }
      securitySchemes:
        oauth:
          type: oauth2
          description: "OAuth2.0認証"
          flows:
            authorizationCode:
              authorizationUrl: https://example.com/api/oauth/dialog
              tokenUrl: https://example.com/api/oauth/token
              scopes:
                write:pets: modify pets in your account
                read:pets: read your pets
    ```



## 参考文献

- [https://github.com/OAI/OpenApi-Specification/blob/main/versions/3.0.3.md](https://github.com/OAI/OpenApi-Specification/blob/main/versions/3.0.3.md)