第22回: JSONレスポンス設計 — 成功とエラーの「構造を統一」してフロントを助ける

章: 第3章: RESTful API設計

APIのレスポンスが「エンドポイントごとにバラバラ」になっていませんか?

成功時は { "user": {...} }、エラー時は { "msg": "error" }、別のエンドポイントでは { "result": "OK" } ——。

フロントエンドがAPIのレスポンスを処理するたびに構造を確認しなければならず、「dataなのかuserなのか」の判断が複雑になります。

JSONレスポンスの構造を統一することで、受け取る側のコードがシンプルになり、エラー処理の漏れも防げます。

JSONレスポンスの基本実装


<?php
function jsonSuccess(mixed $data, int $status = 200): void {
    http_response_code($status);
    header('Content-Type: application/json');
    echo json_encode(['success' => true, 'data' => $data], JSON_UNESCAPED_UNICODE);
}
function jsonError(string $message, int $status = 400): void {
    http_response_code($status);
    header('Content-Type: application/json');
    echo json_encode(['success' => false, 'error' => $message], JSON_UNESCAPED_UNICODE);
}

バラバラな構造 vs 統一された構造

観点 バラバラな構造 統一された構造
フロントの処理 エンドポイントごとに判定コード if (response.success) だけで統一
エラーハンドリング 見つけにくい response.error に必ずある
ドキュメント 全エンドポイントを個別説明 構造の説明が1度で済む
テスト レスポンス構造をエンドポイントごとに確認 統一アサーションが使える

チェックポイント: JSON_UNESCAPED_UNICODE フラグを忘れると日本語がUnicodeエスケープ(\u4e00\u6771等)されてしまいます。

Laravelでの実装


<?php
// Laravelのresponse()->json()を使う
class PostController extends Controller {
    public function show(int $id): JsonResponse {
        $post = Post::findOrFail($id);
        return response()->json([
            'success' => true,
            'data'    => $post,
        ]);
    }

    public function store(Request $request): JsonResponse {
        $post = Post::create($request->validated());
        return response()->json([
            'success' => true,
            'data'    => $post,
        ], 201);
    }
}

// エラーハンドラーでも統一レスポンス
// app/Exceptions/Handler.php で JSON形式のエラーを返す

チェックポイント: LaravelのAPI開発では response()->json() を使い、app/Exceptions/Handler.php でも統一フォーマットのエラーレスポンスを返す設計が推奨されます。

まとめ & 次のステップ

  • JSONレスポンスの success / data / error 構造を統一する
  • HTTPステータスコードとJSONのどちらにも状態を反映させる
  • Laravel APIなら Handler.php でエラーも統一フォーマットにできる

次回はHTTPステータスコードの使い方を学びます。「201なのか200なのか」「422と400の違い」を正確に使い分ける方法です。

Related Articles