OpenAPI
OAS
OpenAPI Specification(OAS)
は、プログラミング言語に依存しないREST API
記述フォーマット。以前はSwagger Specification
と呼ばれている。
YAML
とJSON
yaml
simple-property: a simple value
object-property:
a-property: a value
another-property: another value
array-property:
- item-1-property-1: one
item-1-property-2: 2
- item-2-property-1: three
item-2-property-2: 4
# YAMLのコメント
YAML
では、プロパティ名と二重引用符(" "
)で囲まないYAML
では、JSONの波括弧({}
)とコンマ(,
)を改行やインデントに置き換えYAML
では、配列の鉤括弧({}
)とコンマ(,
)をハイフン(-
)と改行に置き換えJSON
と異なり、YAML
では、ハッシュ記号(#
)で始まるコメントを追加可能
YAMLドキュメントをJSONに変換すると、コメントが消えてしまう点に注意
OAS
記述ツール
OAS
ツール
最小限のOAS
ドキュメント
yaml
openapi: "3.0.0"
# APIの一般情報
info:
title: API
version: "1.0"
# 空のパス
paths: {}
クエリパラメータ
の記述
yaml
paths:
/posts:
get:
tags:
- Post
summary: Retrieve a list of posts
description: Retrieve a paginated list of posts. Specify the page number and the number of posts per page.
parameters:
- name: page # パラメータの名前
in: query # パラメータの場所
required: true # パラメータが必須かどうか
schema: # パラメータのデータ構造の説明
type: integer # パラメータの型(整数)
minimum: 0
default: 1
example: 1
description: The page number to retrieve. Must be a positive integer. Defaults to 1.
- name: rows
in: query
required: true
schema:
type: integer
minimum: 0
default: 10
example: 10
description: The number of posts per page. Must be a positive integer. Defaults to 10.
パスパラメータ
の記述
yaml
paths:
/posts/{id}: # リソースのパスとパラメータ
delete: # 削除するアクション
tags:
- Post
summary: Delete a post
description: Delete an existing post identified by its unique ID.
parameters: # 削除するアクションのパラメータ
- name: id # パスパラメータの名前
in: path # パラメータはパスに配置される
required: true # 必須パラメータ
schema:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426614174000
description: Unique identifier of the post.
OAS
とJSON Schema
を使用しAPI
データを記述
yaml
type: object # このスキーマはオブジェクトを記述
properties: # このプロパティを含んでいる
reference: # プロパティの記述
type: string: # プロパティの型
name: # プロパティの名前
type: string # プロパティの型
property-name: # プロパティの名前
type: number # プロパティの型
Error
スキーマやPost
スキーマをcomponents
セクションで記述し、複数記述を避け、コンポーネント
を再利用
yaml
openapi: 3.1.0
info:
title: Hono API
version: v1
tags:
- name: Hono
description: Endpoints related to general Hono operations
- name: Post
description: Endpoints for creating, retrieving, updating, and deleting posts
components:
schemas:
Error:
type: object
properties:
message:
type: string
required:
- message
Post:
type: object
properties:
id:
type: string
format: uuid
post:
type: string
minLength: 1
maxLength: 140
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
required:
- id
- post
- createdAt
- updatedAt
paths:
/:
get:
tags:
- Hono
summary: Welcome message
description: Retrieve a simple welcome message from the Hono API.
responses:
'200':
description: Successful response with a welcome message.
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Hono🔥
required:
- message
/posts:
post:
tags:
- Post
summary: Create a new post
description: Submit a new post with a maximum length of 140 characters.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
post:
type: string
minLength: 1
maxLength: 140
required:
- post
responses:
'201':
description: Post successfully created.
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
'400':
description: Invalid request due to bad input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
get:
tags:
- Post
summary: Retrieve a list of posts
description: >-
Retrieve a paginated list of posts. Specify the page number and the
number of posts per page.
parameters:
- schema:
type: string
required: true
name: page
in: query
- schema:
type: string
required: true
name: rows
in: query
responses:
'200':
description: Successfully retrieved a list of posts.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Post'
'400':
description: Invalid request due to bad input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/posts/{id}:
put:
tags:
- Post
summary: Update an existing post
description: Update the content of an existing post identified by its unique ID.
parameters:
- schema:
type: string
format: uuid
required: true
name: id
in: path
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
post:
type: string
minLength: 1
maxLength: 140
required:
- post
responses:
'204':
description: Post successfully updated.
'400':
description: Invalid input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Post
summary: Delete a post
description: Delete an existing post identified by its unique ID.
parameters:
- schema:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426614174000
required: true
name: id
in: path
responses:
'204':
description: Post successfully deleted.
'400':
description: Invalid input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Other
Hono Takibi
openapi.yaml
yaml
openapi: 3.1.0
info:
title: Hono API
version: v1
tags:
- name: Hono
description: Endpoints related to general Hono operations
- name: Post
description: Endpoints for creating, retrieving, updating, and deleting posts
components:
schemas:
Error:
type: object
properties:
message:
type: string
required:
- message
Post:
type: object
properties:
id:
type: string
format: uuid
post:
type: string
minLength: 1
maxLength: 140
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
required:
- id
- post
- createdAt
- updatedAt
paths:
/:
get:
tags:
- Hono
summary: Welcome message
description: Retrieve a simple welcome message from the Hono API.
responses:
'200':
description: Successful response with a welcome message.
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Hono🔥
required:
- message
/posts:
post:
tags:
- Post
summary: Create a new post
description: Submit a new post with a maximum length of 140 characters.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
post:
type: string
minLength: 1
maxLength: 140
required:
- post
responses:
'201':
description: Post successfully created.
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
'400':
description: Invalid request due to bad input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
get:
tags:
- Post
summary: Retrieve a list of posts
description: >-
Retrieve a paginated list of posts. Specify the page number and the
number of posts per page.
parameters:
- schema:
type: string
required: true
name: page
in: query
- schema:
type: string
required: true
name: rows
in: query
responses:
'200':
description: Successfully retrieved a list of posts.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Post'
'400':
description: Invalid request due to bad input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/posts/{id}:
put:
tags:
- Post
summary: Update an existing post
description: Update the content of an existing post identified by its unique ID.
parameters:
- schema:
type: string
format: uuid
required: true
name: id
in: path
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
post:
type: string
minLength: 1
maxLength: 140
required:
- post
responses:
'204':
description: Post successfully updated.
'400':
description: Invalid input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Post
summary: Delete a post
description: Delete an existing post identified by its unique ID.
parameters:
- schema:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426614174000
required: true
name: id
in: path
responses:
'204':
description: Post successfully deleted.
'400':
description: Invalid input.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Directory Structure
.
└── openapi.yaml
Command
sh
npx hono-takibi openapi.yaml -o index.ts
Generated
.
├── index.ts
└── openapi.yaml
generated code
ts
import { createRoute, z } from '@hono/zod-openapi'
const errorSchema = z.object({ message: z.string() }).openapi('Error')
const postSchema = z
.object({
id: z.string().uuid(),
post: z.string().min(1).max(140),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
})
.openapi('Post')
export const getRoute = createRoute({
tags: ['Hono'],
method: 'get',
path: '/',
summary: 'Welcome message',
description: 'Retrieve a simple welcome message from the Hono API.',
responses: {
200: {
description: 'Successful response with a welcome message.',
content: {
'application/json': {
schema: z.object({ message: z.string().openapi({ example: 'Hono🔥' }) }),
},
},
},
},
})
export const postPostsRoute = createRoute({
tags: ['Post'],
method: 'post',
path: '/posts',
summary: 'Create a new post',
description: 'Submit a new post with a maximum length of 140 characters.',
request: {
body: {
required: true,
content: { 'application/json': { schema: z.object({ post: z.string().min(1).max(140) }) } },
},
},
responses: {
201: {
description: 'Post successfully created.',
content: { 'application/json': { schema: z.object({ message: z.string() }) } },
},
400: {
description: 'Invalid request due to bad input.',
content: { 'application/json': { schema: errorSchema } },
},
500: {
description: 'Internal server error.',
content: { 'application/json': { schema: errorSchema } },
},
},
})
export const getPostsRoute = createRoute({
tags: ['Post'],
method: 'get',
path: '/posts',
summary: 'Retrieve a list of posts',
description:
'Retrieve a paginated list of posts. Specify the page number and the number of posts per page.',
request: { query: z.object({ page: z.string(), rows: z.string() }) },
responses: {
200: {
description: 'Successfully retrieved a list of posts.',
content: { 'application/json': { schema: z.array(postSchema) } },
},
400: {
description: 'Invalid request due to bad input.',
content: { 'application/json': { schema: errorSchema } },
},
500: {
description: 'Internal server error.',
content: { 'application/json': { schema: errorSchema } },
},
},
})
export const putPostsIdRoute = createRoute({
tags: ['Post'],
method: 'put',
path: '/posts/{id}',
summary: 'Update an existing post',
description: 'Update the content of an existing post identified by its unique ID.',
request: {
body: {
required: true,
content: { 'application/json': { schema: z.object({ post: z.string().min(1).max(140) }) } },
},
params: z.object({ id: z.string().uuid() }),
},
responses: {
204: { description: 'Post successfully updated.' },
400: {
description: 'Invalid input.',
content: { 'application/json': { schema: errorSchema } },
},
500: {
description: 'Internal server error.',
content: { 'application/json': { schema: errorSchema } },
},
},
})
export const deletePostsIdRoute = createRoute({
tags: ['Post'],
method: 'delete',
path: '/posts/{id}',
summary: 'Delete a post',
description: 'Delete an existing post identified by its unique ID.',
request: {
params: z.object({
id: z
.string()
.uuid()
.openapi({
param: { name: 'id', in: 'path' },
example: '123e4567-e89b-12d3-a456-426614174000',
}),
}),
},
responses: {
204: { description: 'Post successfully deleted.' },
400: {
description: 'Invalid input.',
content: { 'application/json': { schema: errorSchema } },
},
500: {
description: 'Internal server error.',
content: { 'application/json': { schema: errorSchema } },
},
},
})