カテゴリ: Spring 更新日: 2025/10/12

Spring Bootの共通エラーレスポンス設計:Problem+JSON風フォーマットを作る

Spring Bootの共通エラーレスポンス設計:Problem+JSON風フォーマットを作る
Spring Bootの共通エラーレスポンス設計:Problem+JSON風フォーマットを作る

先生と生徒の会話形式で理解しよう

生徒

「Spring Bootでエラーメッセージを統一した形で返す方法ってありますか?」

先生

「良い視点ですね。REST APIの開発では、共通のエラーレスポンスを設計しておくことで、利用者がとても理解しやすくなります。」

生徒

「なるほど!具体的にはどんなフォーマットが使われてるんですか?」

先生

「最近では、Problem+JSON形式という標準に沿ったフォーマットを参考にした設計がよく使われています。それでは、実装のポイントを一緒に見ていきましょう。」

1. Spring Bootで共通エラーレスポンスを作る理由とは?

1. Spring Bootで共通エラーレスポンスを作る理由とは?
1. Spring Bootで共通エラーレスポンスを作る理由とは?

Spring BootのREST APIでは、バリデーションエラーや認可エラー、内部サーバーエラーなど様々なエラーが発生します。これらをすべてバラバラの形式で返してしまうと、フロントエンド側やクライアント側が扱いにくくなります。

そこで登場するのが「共通エラーレスポンス設計」です。これにより、すべてのエラーが統一された形式で返され、API利用者はエラーをパースしやすくなります。

その中でも注目されているのが「Problem+JSON」風のフォーマットです。RFC7807という仕様に基づいており、エラー情報をtypetitlestatusdetailinstanceといった項目で表現します。

2. Problem+JSON風フォーマットの基本構造

2. Problem+JSON風フォーマットの基本構造
2. Problem+JSON風フォーマットの基本構造

Problem+JSON形式は、次のようなJSON構造でエラー情報を返すことを前提としています:


{
    "type": "https://example.com/errors/not-found",
    "title": "Resource Not Found",
    "status": 404,
    "detail": "指定されたユーザーが見つかりません。",
    "instance": "/api/users/123"
}

この構造のメリットは、API利用者がstatusコードだけでなく、typetitleなどでエラーの種類や発生場所を把握しやすくなる点にあります。

3. Spring Bootで共通エラーのレスポンスクラスを作成

3. Spring Bootで共通エラーのレスポンスクラスを作成
3. Spring Bootで共通エラーのレスポンスクラスを作成

まずは、共通のレスポンスとして使うクラスを作成します。Javaで@Builder@Getterを使えば、簡単に定義できます。


public class ApiError {
    private String type;
    private String title;
    private int status;
    private String detail;
    private String instance;

    // コンストラクタやgetter/setterはLombokでもOK
}

4. @ControllerAdviceを使って例外をグローバルにハンドリング

4. @ControllerAdviceを使って例外をグローバルにハンドリング
4. @ControllerAdviceを使って例外をグローバルにハンドリング

Spring Bootで例外を一元的に扱うには、@ControllerAdviceを使います。これを使うことで、全コントローラに対する例外処理を共通化できます。


@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ApiError> handleNotFound(ResourceNotFoundException ex, HttpServletRequest request) {
        ApiError error = new ApiError();
        error.setType("https://example.com/errors/not-found");
        error.setTitle("リソースが見つかりません");
        error.setStatus(HttpStatus.NOT_FOUND.value());
        error.setDetail(ex.getMessage());
        error.setInstance(request.getRequestURI());

        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    // 他の例外も同様に追加可能
}

5. 実際のレスポンス例

5. 実際のレスポンス例
5. 実際のレスポンス例

たとえば、存在しないユーザーIDを指定してリクエストした場合、次のようなエラーが返されます。


{
"type": "https://example.com/errors/not-found",
"title": "リソースが見つかりません",
"status": 404,
"detail": "ユーザーIDが存在しません。",
"instance": "/api/users/999"
}

これにより、フロントエンド側はレスポンスのstatustypeを見て、適切な処理(アラート表示や遷移)を実装できます。

6. Problem+JSON形式に合わせたContent-Typeの指定

6. Problem+JSON形式に合わせたContent-Typeの指定
6. Problem+JSON形式に合わせたContent-Typeの指定

RFC7807に準拠するなら、Content-Typeヘッダーにapplication/problem+jsonを指定します。

Spring BootでContent-Typeを返すには、レスポンスエンティティに設定を加えます。


return ResponseEntity
    .status(HttpStatus.NOT_FOUND)
    .contentType(MediaType.valueOf("application/problem+json"))
    .body(error);

7. 独自のバリデーションエラーや認可エラーにも対応

7. 独自のバリデーションエラーや認可エラーにも対応
7. 独自のバリデーションエラーや認可エラーにも対応

MethodArgumentNotValidExceptionなどのバリデーションエラーも、Problem+JSON形式で返すことで、クライアントはdetailの内容を元にフィールドごとのエラーメッセージを表示できます。

また、AccessDeniedExceptionAuthenticationExceptionに対しても、適切なstatustitleを返すように設計しておくと、セキュリティ面での制御がしやすくなります。

8. Spring BootでAPIエラーを美しく扱うコツ

8. Spring BootでAPIエラーを美しく扱うコツ
8. Spring BootでAPIエラーを美しく扱うコツ

Spring Bootでの共通エラーレスポンス設計は、API開発において非常に重要な要素です。Problem+JSON風の統一フォーマットを用いることで、APIの使いやすさや保守性が飛躍的に向上します。

実装はシンプルですが、利用者にとっては大きなメリットとなるため、ぜひ導入を検討してみてください。

カテゴリの一覧へ
新着記事
Javaのラムダ式で戻り値とvoidの使い方を解説!returnの書き方も完全理解
Javaのメソッド参照とコンストラクタ参照の使い方を完全ガイド!初心者向けに::とClass::newを解説
Javaのラムダ式の書き方を徹底解説!アロー演算子->の基本と使い方
Thymeleafのth:eachの使い方!ループ回数やindexなどの繰り返し処理を学ぼう
人気記事
No.1
Java&Spring記事人気No1
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.2
Java&Spring記事人気No2
Spring Boot JPA入門:エンティティ/リポジトリの基本と作り方
No.3
Java&Spring記事人気No3
Javaの@Validアノテーションを徹底解説!初心者でもわかる入力値検証の基本
No.4
Java&Spring記事人気No4
Springの@Repositoryアノテーションの使い方を徹底解説!初心者でもわかるSpringフレームワークのデータアクセス