@RequestBodyの使い方と引数を徹底解説!【初心者向け】

こんにちは!今回は、Spring FrameworkでHTTPリクエストのボディ部分を受け取るためのアノテーション、@RequestBodyについて詳しく解説します。@RequestBodyを使うことで、クライアントから送信されたデータを簡単にサーバー側で取得し、処理できるようになります。


@RequestBodyとは?

@RequestBodyとは、HTTPリクエストのボディ部分に含まれているデータを、メソッドの引数として受け取るためのアノテーションです。通常、POST、PUT、PATCHリクエストのデータを処理する際に利用されます。

たとえば、クライアントからJSON形式のデータが送られてきた場合、@RequestBodyを使って、そのJSONデータをJavaオブジェクトに変換し、利用できるようにすることができます。


基本的な使い方

まずは、@RequestBodyの基本的な使い方を見ていきましょう。以下は、ユーザー情報を登録するシンプルなREST APIの例です。

サーバー側のコード

@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
    User savedUser = userService.saveUser(user);
    return ResponseEntity.ok(savedUser);
}

このコードでは、クライアントから送信されたリクエストボディのデータ(JSON形式)が、自動的にUserというJavaオブジェクトにマッピングされ、userService.saveUser(user)で保存されます。

クライアント側のコード

クライアントは、次のようにユーザー情報を含んだPOSTリクエストを送信します。

const user = { 
  name: "John Doe", 
  email: "john@example.com" 
};

fetch("http://localhost:8080/users", {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(user)
});

このリクエストによって、@RequestBodyはリクエストボディを受け取り、Userオブジェクトとして扱います。


JSONデータをJavaオブジェクトにマッピングする

@RequestBodyは通常、リクエストボディに含まれるJSONデータを、適切なJavaオブジェクトに自動的に変換します。これを「デシリアライズ」と呼びます。このデシリアライズは、Springが内部で使用しているHttpMessageConverterというコンポーネントによって処理されます。デフォルトでは、Jacksonというライブラリが使われ、JSON形式のデータがJavaオブジェクトに変換されます。

{
  "name": "John Doe",
  "email": "john@example.com"
}

上記のJSONデータは、次のようなUserクラスにマッピングされます。

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

    // ゲッターとセッター
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

@RequestBodyの応用【複数フィールドやネストしたオブジェクト】

@RequestBodyは、単純なフィールドだけでなく、ネストしたオブジェクトやリストを含む複雑なデータ構造も受け取ることができます。

複雑なデータ構造の例

例えば、ユーザーが複数の住所情報を持つ場合、次のようにしてネストされたオブジェクトをリクエストボディから取得できます。

{
  "name": "John Doe",
  "email": "john@example.com",
  "addresses": [
    {
      "street": "123 Main St",
      "city": "New York"
    },
    {
      "street": "456 Broadway",
      "city": "Los Angeles"
    }
  ]
}

このJSONデータに対応するJavaクラスは以下のように定義します。

public class User {
    private String name;
    private String email;
    private List<Address> addresses;

    // ゲッターとセッター

    public static class Address {
        private String street;
        private String city;

        // ゲッターとセッター
    }
}

サーバー側コードの例

@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
    return ResponseEntity.ok(userService.saveUser(user));
}

このようにして、クライアントから送られてきた複雑なデータ構造を、@RequestBodyで簡単に取得できます。


バリデーションの組み合わせ

@RequestBodyは、バリデーションアノテーションと組み合わせることができます。@Validアノテーションを使用することで、送信されたデータに対して適切なバリデーションを行い、不正なデータが送られてきた場合には、エラーメッセージを返すことができます。

例: バリデーション付きリクエストボディ

@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user, BindingResult result) {
    if (result.hasErrors()) {
        return ResponseEntity.badRequest().build();
    }
    return ResponseEntity.ok(userService.saveUser(user));
}

@Validを使うことで、Userクラスに設定したバリデーション(例: @NotNull@Emailなど)が自動的に適用されます。

public class User {

    @NotNull
    private String name;

    @Email
    private String email;

    // ゲッターとセッター
}

@RequestBodyとMap型の使用

特定のデータ型に縛られたくない場合、Map<String, Object>を使って、任意のキーと値のペアを受け取ることも可能です。

Map型のリクエストボディ

@PostMapping("/users")
public ResponseEntity<User> updateUser(@RequestBody Map<String, Object> updates) {
    Long userId = (Long) updates.get("id");
    String newEmail = (String) updates.get("email");
    // 更新処理
    return ResponseEntity.ok(userService.updateUser(userId, newEmail));
}

このように、クライアントから送信された任意のフィールドを柔軟に処理することができます。


@RequestBodyの引数

1. 必須属性

デフォルトでは、@RequestBodyは必須です。もしリクエストボディが送信されない場合、400 Bad Requestエラーが発生します。これを回避したい場合は、required = false属性を使用します。

@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody(required = false) User user) {
    if (user == null) {
        return ResponseEntity.badRequest().build();
    }
    return ResponseEntity.ok(userService.saveUser(user));
}

2. consumes属性

@RequestBody@PostMappingでは、consumes属性を使って、どのメディアタイプのリクエストボディを受け取るか指定できます。

@PostMapping(value = "/users", consumes = "application/json")
public ResponseEntity<User> createUser(@RequestBody User user) {
    return ResponseEntity.ok(userService.saveUser(user));
}

consumes属性を使うことで、特定のコンテンツタイプにのみ対応したエンドポイントを定義することができます。


まとめ

@RequestBodyは、リクエストのボディ部分をJavaオブジェクトとして受け取るための非常に便利なアノテーションです。基本的な使い方から、ネストされたオブジェクトの処理、バリデーションの組み合わせ、Map型の柔軟な使用方法まで、さまざまなシナリオで活用できます。

もっと詳しく知りたい方は、Spring公式ドキュメントを見てみてくださいね。

他の記事が見たい方はこちら!↓↓↓

タイトルとURLをコピーしました