ストーリー
高橋アーキテクトがチェックリストを取り出した。
命名規則
URL設計の基本ルール
// ルール1: リソースは複数形の名詞
GET /api/v1/users // Good
GET /api/v1/user // Bad(単数形)
GET /api/v1/getUsers // Bad(動詞)
// ルール2: ケバブケース(小文字 + ハイフン)
GET /api/v1/order-items // Good
GET /api/v1/orderItems // Bad(camelCase)
GET /api/v1/order_items // Bad(snake_case)
// ルール3: ネストは2階層まで
GET /api/v1/users/123/orders // Good(2階層)
GET /api/v1/users/123/orders/456 // Good(2階層 + ID)
GET /api/v1/users/123/orders/456/items/789 // Bad(3階層は深すぎ)
// 深いネストの代替案
GET /api/v1/order-items/789 // 直接アクセス
GET /api/v1/order-items?orderId=456 // クエリパラメータで絞り込み
JSON フィールドの命名
// camelCase で統一(JavaScript/TypeScript の慣習に合わせる)
{
"userId": "usr_123",
"firstName": "太郎",
"lastName": "田中",
"emailAddress": "tanaka@example.com",
"createdAt": "2025-01-15T09:00:00Z",
"isActive": true
}
// snake_case も許容される(Ruby/Python 系のAPI)
{
"user_id": "usr_123",
"first_name": "太郎",
"last_name": "田中"
}
// 重要: プロジェクト内で統一すること
ページネーション
3つの方式
// 方式1: オフセットベース(最も一般的)
GET /api/v1/users?page=2&perPage=20
// レスポンス
{
"data": [...],
"meta": {
"currentPage": 2,
"perPage": 20,
"totalCount": 150,
"totalPages": 8
}
}
// 方式2: カーソルベース(大規模データ向け)
GET /api/v1/users?cursor=eyJpZCI6MTIzfQ&limit=20
// レスポンス
{
"data": [...],
"meta": {
"nextCursor": "eyJpZCI6MTQzfQ",
"hasMore": true
}
}
// 方式3: キーセットページネーション
GET /api/v1/users?after=usr_123&limit=20
方式の使い分け
| 方式 | 特徴 | 適する場面 |
|---|---|---|
| オフセットベース | 任意のページにジャンプ可能 | 管理画面、小〜中規模データ |
| カーソルベース | パフォーマンスが安定 | SNSのタイムライン、大規模データ |
| キーセット | カーソルの改良版 | リアルタイムデータ |
フィルタリング
クエリパラメータによるフィルタリング
// 基本的なフィルタ
GET /api/v1/products?category=electronics
GET /api/v1/products?minPrice=1000&maxPrice=5000
GET /api/v1/products?status=active
// 複数値のフィルタ(カンマ区切り)
GET /api/v1/products?category=electronics,books
// 日付範囲
GET /api/v1/orders?createdAfter=2025-01-01&createdBefore=2025-01-31
// 検索(部分一致)
GET /api/v1/users?search=tanaka
GET /api/v1/products?q=wireless+keyboard
TypeScript での実装例
interface ProductFilter {
category?: string;
minPrice?: number;
maxPrice?: number;
status?: 'active' | 'inactive' | 'draft';
search?: string;
}
interface PaginationParams {
page?: number;
perPage?: number;
}
// フィルタをクエリパラメータに変換
function buildQueryString(
filter: ProductFilter,
pagination: PaginationParams
): string {
const params = new URLSearchParams();
if (filter.category) params.set('category', filter.category);
if (filter.minPrice) params.set('minPrice', String(filter.minPrice));
if (filter.maxPrice) params.set('maxPrice', String(filter.maxPrice));
if (filter.status) params.set('status', filter.status);
if (filter.search) params.set('search', filter.search);
if (pagination.page) params.set('page', String(pagination.page));
if (pagination.perPage) params.set('perPage', String(pagination.perPage));
return params.toString();
}
// 使用例
const query = buildQueryString(
{ category: 'electronics', minPrice: 1000 },
{ page: 1, perPage: 20 }
);
// → "category=electronics&minPrice=1000&page=1&perPage=20"
ソート
ソートパラメータの設計
// 方式1: sort パラメータ(推奨)
GET /api/v1/products?sort=price // 価格の昇順
GET /api/v1/products?sort=-price // 価格の降順(- プレフィックス)
GET /api/v1/products?sort=-createdAt // 作成日の降順
// 方式2: 複数フィールドでのソート
GET /api/v1/products?sort=-price,name // 価格降順、同一価格は名前昇順
// 方式3: sortBy + sortOrder(明示的)
GET /api/v1/products?sortBy=price&sortOrder=desc
フィールド選択(Sparse Fieldsets)
// 必要なフィールドだけを取得(帯域の節約)
GET /api/v1/users/123?fields=name,email
// → { "name": "田中太郎", "email": "tanaka@example.com" }
// リレーションの展開
GET /api/v1/users/123?include=orders,profile
// → ユーザー情報に加えて、注文とプロフィールも含めて返す
コンテンツネゴシエーション
Accept ヘッダー
// クライアントが望むレスポンス形式を指定
GET /api/v1/users/123
Accept: application/json
// サーバーのレスポンス
Content-Type: application/json
{
"id": "123",
"name": "田中太郎"
}
// CSVで欲しい場合
GET /api/v1/reports/sales
Accept: text/csv
// PDFで欲しい場合
GET /api/v1/invoices/123
Accept: application/pdf
まとめ
| ベストプラクティス | ルール |
|---|---|
| URL設計 | 複数形の名詞、ケバブケース、ネスト2階層まで |
| JSON命名 | camelCase で統一 |
| ページネーション | オフセット or カーソル(規模に応じて選択) |
| フィルタリング | クエリパラメータで条件指定 |
| ソート | sort パラメータ、- プレフィックスで降順 |
| フィールド選択 | fields パラメータで必要なフィールドのみ取得 |
| コンテンツネゴシエーション | Accept ヘッダーで形式を指定 |
チェックリスト
- URL設計の基本ルール(複数形、ケバブケース、ネスト制限)を理解した
- 3つのページネーション方式の違いと使い分けを把握した
- フィルタリングとソートのクエリパラメータ設計を理解した
- フィールド選択とコンテンツネゴシエーションを把握した
次のステップへ
API設計のベストプラクティスを学びました。
次のセクションでは、エラーハンドリングの設計を学びます。 クライアントに適切なエラー情報を返すことは、API設計者の重要な責務です。
推定読了時間: 25分