Dev Study
← 解説「リクエストボディと @Body」に戻る

サンプルコードで身につける: リクエストボディと @Body

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1@Body の最小例

POST のボディ全体をオブジェクトとして受け取る最小例です。JSON のパースはフレームワークが済ませてくれるので、ハンドラには最初からオブジェクトが届くという感覚を掴みます。

import { Body, Controller, Post } from "@nestjs/common";

@Controller("tasks")
export class TasksController {
  @Post() // POST /tasks
  create(@Body() body: { title: string }) {
    // { "title": "買い物" } と送ると body.title で取れる
    return { created: body.title };
  }
}

2特定のキーだけ取り出す

@Body("キー名") でボディの一部だけを受け取る例です。1項目だけ更新するような小さなエンドポイントでは、ボディ全体を受けるよりも引数の意図が明確になります。

import { Body, Controller, Post } from "@nestjs/common";

@Controller("settings")
export class SettingsController {
  @Post("theme")
  changeTheme(@Body("theme") theme: string) {
    // { "theme": "dark", "other": 1 } が来ても "dark" だけ取れる
    return { theme };
  }

  @Post("notifications")
  toggle(@Body("enabled") enabled: boolean) {
    return { enabled };
  }
}

3型注釈は実行時には効かない

@Body() 相当の処理をプレーン TypeScript で再現し、型注釈が実行時には何も保証しないことを確かめる例です。クライアントが数値のつもりで文字列を送ると静かに計算が壊れる、という後の検証レッスンへの動機付けになります。

TypeScript

4@Patch — 部分更新とボディの組み合わせ

URL のパラメータで対象を指定し、ボディで変更内容を送る部分更新の定番形です。PATCH は「送られた項目だけ更新」、PUT は「全体を置き換え」という HTTP メソッドの使い分けも合わせて押さえます。

import { Body, Controller, Param, Patch } from "@nestjs/common";

@Controller("users")
export class UsersController {
  // PATCH /users/42 — 送られてきた項目だけ更新する
  @Patch(":id")
  update(
    @Param("id") id: string,
    @Body() body: { name?: string; age?: number },
  ) {
    return { id, updatedFields: Object.keys(body) };
  }
}
// 「対象は URL、変更内容はボディ」という役割分担が REST の定石

5ログインAPIの受け取り口

実務で必ず書くことになるログインエンドポイントの入口部分です。認証情報もただの JSON ボディとして届くこと、ログインは作成ではないので 201 より 200 が自然なことを示します。認証処理そのものは後のレッスンで扱います。

import { Body, Controller, HttpCode, Post } from "@nestjs/common";

@Controller("auth")
export class AuthController {
  @Post("login") // POST /auth/login
  @HttpCode(200) // 「作成」ではないので 201 ではなく 200 に
  login(@Body() body: { email: string; password: string }) {
    // 実務ではここで認証処理に引き渡す
    // パスワードをログやレスポンスに出さないのが鉄則
    return { loggedInAs: body.email };
  }
}