Spring Bootの@RequestBodyでJSONを受け取る使い方を解説する記事のアイキャッチ。若手エンジニアがJava道場風の学習空間でAPI入力を学ぶイラスト。

Spring

Spring Bootの@RequestBodyとは?JSONを受け取る使い方と注意点

AIによる要約

@RequestBodyは、HTTPリクエストのボディに入っているJSONをJavaオブジェクトへ変換して受け取るために使います。クエリ文字列やHTMLフォームを受けるためのものではありません。APIの入口ではRequest DTOとセットで考えると安全です。

新人SE
新人SE
JSONを受け取るControllerでは、@RequestParamではなく@RequestBodyを使うんですか?
ポンコツSE
ポンコツSE
はい。JSONはリクエストボディに入るので@RequestBodyで受けます。URLの後ろに付く条件やHTMLフォームとは受け取り方が違います。

Spring BootでAPIを作ると、@RequestBodyがよく出てきます。

画面フォーム中心の開発から入った人は、@RequestParamやFormクラスとの違いが分からず、JSONがnullになる、400エラーになる、といった問題にぶつかりやすいです。

この記事のポイント

  • @RequestBodyはJSONなどのリクエストボディを受け取る
  • HTMLフォームやクエリ文字列とは受け取り方が違う
  • APIではRequest DTOを用意してEntityと分ける
  • Content-TypeやJSONの項目名ずれに注意する

@RequestBodyはリクエストボディを読む

@RequestBodyは、HTTPリクエストのボディに入っているデータをJavaオブジェクトへ変換します。Spring BootのAPIでは、JSONを受け取るときによく使います。

@PostMapping("/api/users")
public ResponseEntity<Void> create(@RequestBody UserCreateRequest request) {
    userService.create(request);
    return ResponseEntity.ok().build();
}

このControllerは、リクエストボディのJSONをUserCreateRequestへ変換して受け取ります。

送信されるJSONの例

POST /api/users
Content-Type: application/json

{
  "name": "田中",
  "email": "tanaka@example.com"
}

このJSONのnameemailが、Request DTOのフィールドへ対応します。項目名がずれると値が入りません。

public class UserCreateRequest {
    private String name;
    private String email;

    // getter / setter
}

@RequestParamとの違い

@RequestParamは、主にクエリ文字列やフォームの単発パラメータを受け取ります。JSONボディを受け取るためのものではありません。

// クエリ文字列を受ける
@GetMapping("/api/users")
public List<UserResponse> search(@RequestParam String keyword) {
    return userService.search(keyword);
}

// JSONボディを受ける
@PostMapping("/api/users")
public ResponseEntity<Void> create(@RequestBody UserCreateRequest request) {
    userService.create(request);
    return ResponseEntity.ok().build();
}

URLの後ろに付く値なのか、本文として送られるJSONなのかで使い分けます。

入力チェックは@Validと組み合わせる

APIでも入力チェックは必要です。Request DTOに制約を付け、Controllerで@Validを付けます。

public class UserCreateRequest {
    @NotBlank
    private String name;

    @NotBlank
    @Email
    private String email;
}

@PostMapping("/api/users")
public ResponseEntity<Void> create(@RequestBody @Valid UserCreateRequest request) {
    userService.create(request);
    return ResponseEntity.ok().build();
}

画面フォームと違い、APIではエラー時に画面へ戻すのではなく、400レスポンスとしてエラー内容を返す設計が多いです。

Entityを直接受け取らない

APIでも、Entityを@RequestBodyで直接受けるのは避けた方がよいことが多いです。

// 避けたい例
@PostMapping("/api/users")
public ResponseEntity<Void> create(@RequestBody User user) {
    userRepository.save(user);
    return ResponseEntity.ok().build();
}

DBの構造や更新させたくない項目がAPIに漏れる可能性があります。Request DTOを作り、Serviceで必要な形へ変換しましょう。

400エラーになったときの確認ポイント

確認リスト

  • Content-Type: application/jsonになっているか
  • JSONの項目名とRequest DTOのフィールド名が合っているか
  • Request DTOにgetter/setterやコンストラクタが適切にあるか
  • JSONの文法が壊れていないか
  • 入力チェックで弾かれていないか

この記事とあわせて読みたい

まとめ

@RequestBodyは、JSONなどのリクエストボディをJavaオブジェクトとして受け取るためのアノテーションです。

クエリなら@RequestParam、URLの一部なら@PathVariable、JSONなら@RequestBody。この区別ができると、APIのControllerを読みやすくなります。

-Spring
-, , , ,