0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SpringBootでAPIを実装する際のリクエスト/レスポンスの操作を学ぶ

Last updated at Posted at 2024-11-30

はじめに

最近、SpringBootについて学んでいます。今回はリクエスト、レスポンスをJSONで扱う方法を整理します。

今回の想定

今回は以下の機能を題材にしてみます。

  • request
    • firstNum,secondNumを引数で受け取る
  • response
    • 足した結果をresultに設定して返す

controllerの実装

まずは実装例から。
それぞれ整理していきましょう。

@RestController
public class CalculationController {

    @PostMapping("/calculate")
    public CalculationResponse calculate(@RequestBody CalculationRequest request) {
        // レスポンスオブジェクトを作成
        CalculationResponse response = new CalculationResponse();

        // 計算処理
        int result = request.getFirstNum() + request.getSecondNum();

        // 結果を設定
        response.setResult(result);

        return response;
    }
}

RestController

RESTの場合は、@RestControllerを使用します。@Controllerもありますが、こちらはMVCなどで、テンプレート(HTML)を返す場合に使用します。

このアノテーションによって、該当のコントーラーがRESTであることを定義します。

RequestBody

POSTなどで受け取った情報をクラスと紐付けるために使用します。

@RequestBody CalculationRequest requestで、Bodyの内容がCalculationRequestに変換されます

CalculationRequest / CalculationResponse

CalculationRequest

リクエストで受け取るクラスを定義します。

public class CalculationRequest {
    private int firstNum;
    private int secondNum;

    // getter, setter
    public int getFirstNum() {
        return firstNum;
    }

    public void setFirstNum(int firstNum) {
        this.firstNum = firstNum;
    }

    public int getSecondNum() {
        return secondNum;
    }

    public void setSecondNum(int secondNum) {
        this.secondNum = secondNum;
    }
}

CalculationResponse

レスポンスのクラスを定義します。

public class CalculationResponse {
    private int result;

    // getter, setter
    public int getResult() {
        return result;
    }

    public void setResult(int result) {
        this.result = result;
    }
}

実際のAPIの動き

実装したAPIの動作を確認してみましょう。以下にcurlコマンドを使用したリクエスト例と、それに対するレスポンスを示します。

curl -X POST http://localhost:8080/calculate \
-H "Content-Type: application/json" \
-d '{
    "firstNum": 10,
    "secondNum": 20
}'
  • リクエスト例
{
    "firstNum": 10,
    "secondNum": 20
}
  • レスポンス例
{
    "result": 30
}

リクエストのJSONとクラスの関係

なんとなく伝わったかもしれませんが、@RequestBodyで指定したクラスにJSONが変換されています。

クラスとJSONの比較

JSONのキーとクラスのフィールド名が一致する場合、自動的にマッピングされます。

public class CalculationRequest {
    private int firstNum;    // ← JSONの"firstNum"と一致
    private int secondNum;   // ← JSONの"secondNum"と一致
}
{
    "firstNum": 10,    //  クラスのfirstNumフィールドにマッピング
    "secondNum": 20    //  クラスのsecondNumフィールドにマッピング
}

マッピングされない例

以下のような場合、正しくマッピングされません。

  1. フィールド名が異なる場合
public class CalculationRequest {
    private int first;    // "firstNum"とは異なる名前
    private int second;   // "secondNum"とは異なる名前
}
{
    "firstNum": 10,    // マッピングされない
    "secondNum": 20    // マッピングされない
}
  1. データ型が一致しない場合
public class CalculationRequest {
    private String firstNum;    // 文字列型で定義
    private int secondNum;      // 数値型で定義
}
{
    "firstNum": 10,     // 数値型のため、String型へのマッピングでエラー
    "secondNum": "20"   // 文字列型のため、int型へのマッピングでエラー
}

これらの場合は、400 Bad Reqestが発生します。

いろいろなパターンの実装例

JSONのフィールドにオブジェクト

オブジェクトをネストすることもできます。

public class UserRequest {
    private String name;
    private Address address;  // オブジェクトをネスト

    // Address クラス
    public static class Address {
        private String city;
        private String street;
        
        // getter, setter
    }
    
    // getter, setter
}
{
    "name": "John",
    "address": {
        "city": "Tokyo",
        "street": "Shibuya 1-1-1"
    }
}

配列

配列やリストも扱えます。

public class BatchCalculationRequest {
    private List<Integer> numbers;  // 数値の配列
    private List<User> users;       // オブジェクトの配列

    // User クラス
    public static class User {
        private String name;
        private int age;
        
        // getter, setter
    }
    
    // getter, setter
}
{
    "numbers": [1, 2, 3, 4, 5],
    "users": [
        {"name": "John", "age": 30},
        {"name": "Jane", "age": 25}
    ]
}

バリデーション

バリデーションをすることも可能です。独自実装も可能ですが。こちらもフレームワークにお任せしましょう。

  • 必要な依存関係の導入
    • それぞれの環境に合わせてspring-boot-starter-validationを導入します。

そして、 controllerで@Validを使用して、バリデーションを有効化します。

@RestController
public class CalculationController {
    @PostMapping("/calculate")
    public CalculationResponse calculate(@Valid @RequestBody CalculationRequest request) {
        // バリデーションエラーの場合、自動的に400エラーが返される
        // ...
    }
}

では、それぞれのクラスでバリデーションを実装してみます。

文字列長チェック

public class UserRequest {
    @NotNull(message = "名前は必須です")
    @Size(min = 1, max = 50, message = "名前は1~50文字で入力してください")
    private String name;

    @Email(message = "メールアドレスの形式が不正です")
    private String email;
    
    // getter, setter
}

数値チェック

public class CalculationRequest {
    @Min(value = 0, message = "0以上の値を入力してください")
    @Max(value = 100, message = "100以下の値を入力してください")
    private int firstNum;

    @Positive(message = "正の値を入力してください")
    private int secondNum;
    
    // getter, setter
}

他にもいろいろあります。独自のルールでバリデーションを実装することも可能です。

まとめ

とても基本的なAPIの流れとして、JSONでリクエストを受けて、JSONのレスポンスを返す方法をまとめました。また、バリデーションの実装方法もみてみました。

すごく基本的ですが、API開発で最初に必要になる部分です。
少しでも参考に、とっかかりのハードルが低くなれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?