OpenAPI 仕様の基礎

OpenAPI 仕様(OAS)は、RESTful API を記述するための標準フォーマットです。

OpenAPI 仕様により、開発者は API の構造、パラメータ、レスポンスなどの情報を機械可読な形式で定義できます。

OpenAPI 仕様は当初 Swagger 仕様と呼ばれていましたが、後に OpenAPI Initiative に寄贈され、OpenAPI に改名されました。

OpenAPI 仕様の主な役割は次のとおりです。

  • API の標準化されたドキュメントの提供
  • API の自動化テストのサポート
  • クライアント SDK の生成
  • フロントエンドとバックエンドの分離開発の促進

OpenAPI には現在、広く使用されている主要なバージョンが2つあります。

  1. OpenAPI 2.0(旧 Swagger 2.0)
  2. OpenAPI 3.x(最新の安定版)

新規プロジェクトでは、より多くの機能と改善が提供されている OpenAPI 3.x バージョンの使用を推奨します。

OpenAPI 仕様の構造

OpenAPI ドキュメントは通常、YAML または JSON 形式で記述されます。

以下は基本的な OpenAPI ドキュメントの構造です。

例

openapi: 3.1.0 # OpenAPI バージョン
info:
title: サンプル API # API の名称
description: これはサンプルの API ドキュメントです
version: 1.0.0 # API バージョン
servers:
- url: https://api.example.com/v1 # API サーバーのアドレス
description: 本番環境
  - url: https://dev-api.example.com/v1
description: 開発環境

paths: # API パスの定義
/users: # エンドポイントのパス
get: # HTTP メソッド
summary: すべてのユーザーを取得
description: システム内のすべてのユーザーリストを返します
      operationId: getUsers
      tags:
- users # グループラベル
parameters: # リクエストパラメータ
        - name: limit
          in: query
description: 返される結果の件数制限
          schema:
            type: integer
            default: 20
responses: # レスポンス定義
'200': # HTTP ステータスコード
description: 成功時にユーザーリストを返します
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
        '400':
description: 不正なリクエストパラメータ

components: # 再利用可能なコンポーネント
schemas: # データモデル定義
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        email:
          type: string
          format: email
      required:
        - id
        - name

OpenAPI の核心概念の詳細

1. ドキュメントメタデータ (info)

info セクションには、タイトル、説明、バージョンなど API の基本情報が含まれます。

例

info:
title: ユーザー管理 API
description: システム内のユーザー情報を管理するための API
  version: 1.0.0
  contact:
name: API サポートチーム
    email: [email protected]
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html

2. サーバー情報 (servers)

servers セクションは、利用可能な API サーバーのリストを定義します。

例

servers:
  - url: https://api.example.com/v1
description: 本番環境
  - url: https://staging-api.example.com/v1
description: テスト環境

3. パス (paths)

paths セクションは、API のすべてのエンドポイントと、それらがサポートする HTTP メソッドを定義します。

例

paths:
  /users:
    get:
# ユーザーリストを取得
    post:
# 新規ユーザーを作成
  /users/{userId}:
    get:
# 特定のユーザーを取得
    put:
# ユーザーを更新
    delete:
# ユーザーを削除

4. 操作 (operations)

各パスの HTTP メソッドが 1 つの API 操作を定義します。

例

paths:
  /users/{userId}:
    get:
summary: ユーザー詳細を取得
description: ユーザー ID に基づいてユーザーの詳細情報を取得します
      operationId: getUserById
      tags:
        - users
      parameters:
        - name: userId
          in: path
          required: true
description: ユーザー ID
          schema:
            type: integer
      responses:
        '200':
description: ユーザー情報の取得に成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
description: ユーザーが存在しません
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

5. パラメータ (parameters)

パラメータは複数の場所に定義できます。

例

parameters:
  - name: userId
in: path # パスパラメータ
    required: true
    schema:
      type: integer
  - name: filter
in: query # クエリパラメータ
    schema:
      type: string
  - name: X-API-Key
in: header # リクエストヘッダーパラメータ
    schema:
      type: string
  - name: trace
in: cookie # Cookie パラメータ
    schema:
      type: string

6. リクエストボディ (requestBody)

POST、PUT などのメソッドのリクエストボディを定義します。

例

requestBody:
description: ユーザーデータ
  required: true
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/User'
    application/x-www-form-urlencoded:
      schema:
        $ref: '#/components/schemas/UserForm'

7. レスポンス (responses)

各操作で発生し得るレスポンスを定義します。

例

responses:
  '200':
description: 操作成功
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/SuccessResponse'
  '400':
description: リクエストパラメータのエラー
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/ErrorResponse'

8. コンポーネント (components)

components セクションは、API ドキュメント全体で再利用できる要素を格納するために使用します。

例

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
          format: email
        roles:
          type: array
          items:
            type: string
            enum: [admin, user, editor]
      required:
        - name
        - email
   
    Error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
      required:
        - code
        - message
 
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
   
    OAuth2:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: https://example.com/oauth/authorize
          scopes:
read: 読み取り権限
write: 書き込み権限

9. データモデル (schemas)

API で使用されるデータ構造を定義します。

例

schemas:
  Product:
    type: object
    properties:
      id:
        type: integer
      name:
        type: string
        maxLength: 100
      price:
        type: number
        format: float
        minimum: 0
      category:
        type: string
        enum: [electronics, books, clothing]

10. セキュリティ (security)

API の認証と認可の方法を定義します。

例

security:
  - ApiKeyAuth: []
  - OAuth2: [read, write]

完全な OpenAPI ドキュメントの例を作成する

以下は、より完全な電子商取引 API の例です。

例

openapi: 3.1.0
info:
title: 電子商取引 API
description: オンラインストアの商品と注文を管理するための API
  version: 1.0.0
  contact:
name: APIサポートチーム
    email: [email protected]
    url: https://api.example.com/support
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.example.com/v1
description: 本番環境
  - url: https://dev-api.example.com/v1
description: 開発環境

tags:
  - name: products
description: 製品関連操作
  - name: orders
description: 注文関連操作
  - name: users
description: ユーザー関連操作

paths:
  /products:
    get:
summary: 製品リストの取得
description: 利用可能なすべての製品のリストを返します。ページネーションとフィルタリングに対応します。
      operationId: getProducts
      tags:
        - products
      parameters:
        - name: category
          in: query
description: 製品カテゴリでフィルタリング
          schema:
            type: string
        - name: page
          in: query
description: ページ番号
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
description: 1ページあたりの件数
          schema:
            type: integer
            default: 20
      responses:
        '200':
description: 製品リストの取得成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                  products:
                    type: array
                    items:
                      $ref: '#/components/schemas/Product'
        '400':
description: パラメータエラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    post:
summary: 新規製品の作成
description: 新しい製品情報を作成します
      operationId: createProduct
      tags:
        - products
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductCreate'
      responses:
        '201':
description: 製品の作成が成功しました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
description: リクエストデータが無効です
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
description: 未認証
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /products/{productId}:
    get:
summary: 製品詳細の取得
description: IDに基づいて特定の製品の詳細情報を取得します
      operationId: getProductById
      tags:
        - products
      parameters:
        - name: productId
          in: path
          required: true
description: 製品ID
          schema:
            type: integer
      responses:
        '200':
description: 製品情報の取得成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '404':
description: 製品が存在しません
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    put:
summary: 製品の更新
description: 特定の製品の情報を更新します
      operationId: updateProduct
      tags:
        - products
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      parameters:
        - name: productId
          in: path
          required: true
description: 製品ID
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductUpdate'
      responses:
        '200':
description: 製品の更新が成功しました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
description: リクエストデータが無効です
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
description: 未認証
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
description: 製品が存在しません
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    delete:
summary: 製品の削除
description: 特定の製品を削除します
      operationId: deleteProduct
      tags:
        - products
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      parameters:
        - name: productId
          in: path
          required: true
description: 製品ID
          schema:
            type: integer
      responses:
        '204':
description: 製品の削除が成功しました
        '401':
description: 未認証
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
description: 製品が存在しません
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /orders:
    get:
summary: 注文リストの取得
description: すべての注文のリストを返します。ページネーションとフィルタリングに対応します。
      operationId: getOrders
      tags:
        - orders
      security:
        - ApiKeyAuth: []
        - OAuth2: [read]
      parameters:
        - name: status
          in: query
description: 注文ステータスでフィルタリング
          schema:
            type: string
            enum: [pending, processing, shipped, delivered, cancelled]
        - name: page
          in: query
description: ページ番号
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
description: 1ページあたりの件数
          schema:
            type: integer
            default: 20
      responses:
        '200':
description: 注文リストの取得成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                  orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
        '401':
description: 未認証
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
   
    post:
summary: 新規注文の作成
description: 新しい注文を作成します
      operationId: createOrder
      tags:
        - orders
      security:
        - ApiKeyAuth: []
        - OAuth2: [write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderCreate'
      responses:
        '201':
description: 注文の作成が成功しました
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
description: リクエストデータが無効です
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
description: 未認証
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

components:
  schemas:
    Product:
      type: object
      properties:
        id:
          type: integer
          format: int64
          readOnly: true
        name:
          type: string
          maxLength: 100
        description:
          type: string
        price:
          type: number
          format: float
          minimum: 0
        category:
          type: string
          enum: [electronics, books, clothing, food]
        inStock:
          type: boolean
          default: true
        createdAt:
          type: string
          format: date-time
          readOnly: true
        updatedAt:
          type: string
          format: date-time
          readOnly: true
      required:
        - name
        - price
        - category
   
    ProductCreate:
      type: object
      properties:
        name:
          type: string
          maxLength: 100
        description:
          type: string
        price:
          type: number
          format: float
          minimum: 0
        category:
          type: string
          enum: [electronics, books, clothing, food]
        inStock:
          type: boolean
          default: true
      required:
        - name
        - price
        - category
   
    ProductUpdate:
      type: object
      properties:
        name:
          type: string
          maxLength: 100
        description:
          type: string
        price:
          type: number
          format: float
          minimum: 0
        category:
          type: string
          enum: [electronics, books, clothing, food]
        inStock:
          type: boolean
   
    Order:
      type: object
      properties:
        id:
          type: integer
          format: int64
          readOnly: true
        userId:
          type: integer
          format: int64
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        totalAmount:
          type: number
          format: float
          readOnly: true
        status:
          type: string
          enum: [pending, processing, shipped, delivered, cancelled]
          default: pending
        shippingAddress:
          $ref: '#/components/schemas/Address'
        createdAt:
          type: string
          format: date-time
          readOnly: true
        updatedAt:
          type: string
          format: date-time
          readOnly: true
      required:
        - userId
        - items
        - shippingAddress
   
    OrderCreate:
      type: object
      properties:
        userId:
          type: integer
          format: int64
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        shippingAddress:
          $ref: '#/components/schemas/Address'
      required:
        - userId
        - items
        - shippingAddress
   
    OrderItem:
      type: object
      properties:
        productId:
          type: integer
          format: int64
        quantity:
          type: integer
          minimum: 1
          default: 1
        unitPrice:
          type: number
          format: float
          readOnly: true
      required:
        - productId
        - quantity
   
    Address:
      type: object
      properties:
        street:
          type: string
        city:
          type: string
        state:
          type: string
        zipCode:
          type: string
        country:
          type: string
      required:
        - street
        - city
        - state
        - zipCode
        - country
   
    Error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
      required:
        - code
        - message
 
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
   
    OAuth2:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: https://example.com/oauth/authorize
          scopes:
read: 読み取り権限
write: 書き込み権限

security:
  - ApiKeyAuth: []

OpenAPI 仕様の基本構文

OpenAPI仕様は2つの形式をサポートしています:

  1. YAML(推奨)
  2. JSON

YAML 形式の例

例

openapi: 3.0.0
info:
title: ペットショップAPI
  version: 1.0.0
paths:
  /pets:
    get:
summary: すべてのペットを一覧表示
      responses:
        '200':
description: ペットリストの取得成功

JSON 形式の例

例

"openapi": "3.0.0",
  "info": {
    "title": "ペットショップAPI",
    "version": "1.0.0"
  },
  "paths": {
    "/pets": {
      "get": {
        "summary": "すべてのペットを一覧表示",
        "responses": {
          "200": {
            "description": "ペットリストの取得成功"
          }
        }
      }
    }
  }
}

OpenAPI 仕様の使用方法

1. OpenAPI ドキュメントの作成と編集

以下のツールを使用してOpenAPIドキュメントを作成および編集できます:

  • Swagger Editor:オンラインエディタ。リアルタイムプレビューと検証を提供します
  • Stoplight Studio:ビジュアルAPI設計ツール
  • VS Code + OpenAPIプラグイン:統合開発環境での編集

2. ドキュメント生成

OpenAPI仕様を使用すると、美しいAPIドキュメントを自動生成できます。一般的なツールは次のとおりです:

  • Swagger UI:インタラクティブなAPIドキュメントを生成
  • ReDoc:レスポンシブでカスタマイズ可能なドキュメントを提供
  • Slate:エレガントな静的ドキュメントを生成

3. コード生成

OpenAPIは多言語のクライアントおよびサーバーコードを自動生成できます:

  • OpenAPI Generator:40以上のプログラミング言語をサポート
  • Swagger Codegen:クライアントおよびサーバーコードを生成
  • NSwag:.NETエコシステム向けのコードジェネレーター

4. API テストとモック

OpenAPI仕様は次の用途にも使用できます:

  • 自動化テスト:Postman、SoapUIなどのツールを使用
  • APIモック:Prism、MicrocksなどはOpenAPI仕様に基づいてAPIをモックできます

ベストプラクティス

1. 設計原則

  • エンドポイントの命名規則を統一する
  • 適切なHTTPメソッドとステータスコードを使用する
  • 明確なURLパス構造を設計する

2. ドキュメントの推奨事項

  • 詳細な説明と例を提供する
  • タグを使用してAPIをグループ化する
  • 必須パラメータを明確に指定する

3. バージョン管理戦略

  • URLにバージョン番号を含める(/v1/users)
  • リクエストヘッダーでバージョンを指定する(Accept: application/vnd.example.v1+json)
  • OpenAPIドキュメントにバージョン情報を明記する

よくある質問と回答

1. OpenAPI と Swagger の違いは?

SwaggerはOpenAPI仕様の前身です。2016年にSwagger仕様はLinux Foundationに寄贈され、OpenAPI仕様に改名されました。現在「Swagger」は通常、OpenAPI仕様を中心に構築されたツール群を指します。

2. OpenAPI 2.0 と 3.x の主な違いは?

OpenAPI 3.xでは多くの新機能が導入されました。例えば:

  • 改善されたコンポーネント再利用
  • より柔軟なリクエストボディ定義
  • より強力なセキュリティ定義
  • 改善されたJSON Schemaサポート
  • links(リンク)とcallbacks(コールバック)のサポート

3. 認証と認可をどのように扱うか?

OpenAPIは複数のセキュリティメカニズムをサポートしています:

  • APIキー
  • HTTP基本認証
  • OAuth2.0
  • OpenID Connect
  • カスタムヘッダー認証

学習リソース

  1. 公式ドキュメント:OpenAPI Initiative
  2. ツール:
  3. 学習リソース:
その他の拡張機能