こんにちは!今回は、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公式ドキュメントを見てみてくださいね。
他の記事が見たい方はこちら!↓↓↓