OpenAPI定義のcomponentsの使い方
概要
この記事では、OpenAPI定義のcomponents
セクションについて解説します。
OpenAPIのcomponentsセクションとは
OpenAPIのcomponents
は、データモデル、レスポンス、クエリ、パス、ヘッダーなど、APIを定義するための要素を再利用可能な形でまとめて定義するセクションです。
API定義は、多くの場合、重複が発生しがちです。例えば、エンドポイントごとに同じ構造のレスポンスを返したり、共通のヘッダやパラメータを持つことがあります。このような重複が積み重なると、API定義は膨大になり、見通しが悪くなります。
このような問題に対処するために使えるのがcomponents
です。components
を使うことで、重複がなくなり、定義書は読みやすく、メンテナンスもしやすくなります。
componentsに定義できる要素
OpenAPIのcomponents
セクションで定義できる要素は、Components Objectのドキュメントに記載されています。
例えば、以下のような要素を定義可能です。これらは、OpenAPI定義書内で再利用できます。
- schemas: データモデル
- responses: レスポンス定義
- parameters: クエリ、パス、ヘッダー、クッキーのパラメータ
- requestBodies: リクエストボディ
- headers: レスポンスやリクエストヘッダー
- examples: サンプルデータ
components未使用のサンプル
以下は、components
を使わずに記載したOpenAPIドキュメントのサンプルです。各レスポンスをそれぞれのエンドポイント内に直接定義しています。
openapi: 3.0.0
info:
title: Sample API
version: 1.0.0
paths:
/users:
get:
summary: Returns a list of users.
responses:
'200':
description: A JSON array of users with details
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: integer
name:
type: string
age:
type: integer
gender:
type: string
example:
- id: 1
name: 桑原 将志
age: 31
gender: male
- id: 2
name: 筒香 嘉智
age: 32
gender: male
- id: 3
name: 牧 秀悟
age: 26
gender: male
'404':
description: "Resource not found"
content:
application/json:
schema:
type: object
properties:
error:
type: string
example: "Resource not found"
'500':
description: "Internal server error"
content:
application/json:
schema:
type: object
properties:
error:
type: string
example: "An unexpected error occurred"
今回の例はエンドポイントが1つなので問題になりませんが、複数のエンドポイントで同じようなレスポンスを返す場合、コードが冗長になる可能性があります。
components使用後のサンプル
components
を使った改善後のサンプルです。
このサンプルでは、
-
200
の時に返却するデータ (components.schemas
で定義) -
404
の時に返却するエラーレスポンス(components.responses
で定義) -
500
の時に返却するエラーレスポンス(components.responses
で定義)
の3つの要素をcomponents
として定義し、使用しています。
openapi: 3.0.0
info:
title: Sample API
version: 1.0.0
paths:
/users:
get:
summary: Returns a list of users.
responses:
'200':
description: A JSON array of users with details
content:
application/json:
schema:
$ref: "#/components/schemas/get_response"
'404':
$ref: "#/components/responses/NotFound"
'500':
$ref: "#/components/responses/InternalServerError"
components:
schemas:
get_response:
description: GET /usersのレスポンス
type: array
items:
type: object
properties:
id:
type: integer
name:
type: string
age:
type: integer
gender:
type: string
example:
- id: 1
name: 桑原 将志
age: 31
gender: male
- id: 2
name: 筒香 嘉智
age: 32
gender: male
- id: 3
name: 牧 秀悟
age: 26
gender: male
responses:
NotFound:
description: "Resource not found"
content:
application/json:
schema:
type: object
properties:
error:
type: string
example: "Resource not found"
InternalServerError:
description: "Internal server error"
content:
application/json:
schema:
type: object
properties:
error:
type: string
example: "An unexpected error occurred"
/users
エンドポイントが返却するレスポンスが一目で分かるようになり、読みやすくなりました。
paths:
/users:
get:
summary: Returns a list of users.
responses:
'200':
description: A JSON array of users with details
content:
application/json:
schema:
$ref: "#/components/schemas/get_response"
'404':
$ref: "#/components/responses/NotFound"
'500':
$ref: "#/components/responses/InternalServerError"
今回のサンプルは、エンドポイントの数もサンプルデータが少ないため、components
の効果を感じにくいかもしれません。しかし、複雑なAPI定義では、同じようなレスポンスやデータ定義が重複するため、components
を使って適切に共通化するのがベターです。
componentsを参照するときは$refを使う
components
で定義した要素を使用する場合は、$ref
を使います。$ref
は、OpenAPI仕様でcomponents
で定義済みの要素を参照する機能で、使用したいcomponents
の階層を指定します。
responses:
'200':
description: A JSON array of users with details
content:
application/json:
schema:
$ref: "#/components/schemas/get_response"
'404':
$ref: "#/components/responses/NotFound"
'500':
$ref: "#/components/responses/InternalServerError"
最後に
OpenAPI定義はダラダラ書いていると、とてつもなく長くなってしまったりするので、components
は積極的に活用したいですね。
Discussion