DevToolBox

JSON Schemaで型を保証する基本 - API契約と設定ファイルを壊さない

最終更新日: 2026年4月19日

「フロントが期待するレスポンス形式とサーバが返すJSONがズレていて、undefined参照で画面が真っ白になった」 「設定ファイルのキー名をtypoしたまま本番デプロイした」。 こうした事故の大半はJSON Schemaによる型チェックで防げます。 この記事ではJSON Schemaの基本文法と、実際にAPIや設定ファイルを守るための実装パターンをまとめます。

図1: JSON Schemaはデータとコードの間の「契約書」

データ
APIレスポンス / 設定ファイル / フォーム入力
JSON Schema
型・必須・値域を宣言的に定義
アプリ
検証に通ったデータだけを処理

スキーマで弾けば、不正データがビジネスロジックまで到達しない

最小のスキーマ

ユーザー登録APIのリクエストを想定します。emailage が必須、age は0〜150の整数という契約です。

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["email", "age"],
  "properties": {
    "email": { "type": "string", "format": "email" },
    "age":   { "type": "integer", "minimum": 0, "maximum": 150 }
  },
  "additionalProperties": false
}

ポイントは additionalProperties: false です。 これを付けないと未知のキーが紛れても通ってしまい、typoに気付けません。 逆に拡張を許したい場合は明示的に true を指定します。

よく使うキーワード早見表

キーワード用途
type基本型の指定string, integer, boolean, array, object, null
required必須プロパティの配列["id", "name"]
enum許可する値を列挙["draft", "published"]
const単一の固定値"v2"
pattern正規表現での検証"^[A-Z]{3}$"
minimum / maximum数値の範囲価格なら 0 以上
minLength / maxLength文字列の長さパスワード長の下限など
format意味的な型(検証は実装依存)email, uri, date-time, uuid
additionalProperties未知キーを許すか基本 false 推奨

Node.jsでAjvを使って検証する

実務で最も使われるバリデータは Ajv。 Fastify や tRPC のバリデータ層の中身もAjvです。

import Ajv from "ajv";
import addFormats from "ajv-formats";

const ajv = new Ajv({ allErrors: true, strict: true });
addFormats(ajv); // format: email / uri などを有効化

const schema = {
  type: "object",
  required: ["email", "age"],
  properties: {
    email: { type: "string", format: "email" },
    age:   { type: "integer", minimum: 0, maximum: 150 },
  },
  additionalProperties: false,
};

const validate = ajv.compile(schema);
const data = { email: "test@example.com", age: 30 };

if (!validate(data)) {
  console.error(validate.errors);
  // [{ instancePath: "/age", message: "must be <= 150", ... }]
}

allErrors: true で「全エラーをまとめて返す」動作になります。 デフォルトだと最初のエラーで打ち切るため、フォーム検証用途では基本有効化しておくのが無難です。

図2: バリデーション層の配置

クライアント(ブラウザ・SDK)
↓ リクエスト
✔ JSON Schemaバリデーション
不正なら400 Bad Requestで即返す
↓ 通過したリクエストのみ
ビジネスロジック / DB
↑ レスポンス
✔ レスポンスも検証(契約テスト)
サーバ側の破壊的変更に早期に気付ける

TypeScriptの型と同期する

同じ情報を型とスキーマに二重メンテするのは地獄です。現実的な選択肢は2つ。

既にOpenAPIを運用しているなら、その中にJSON Schemaがそのまま含まれているため、 OpenAPI定義をsource of truthにしてクライアント型・バリデータを生成する方が一貫します。

設定ファイル(tsconfig.json / package.jsonなど)を守る

VS Codeは $schema フィールドを尊重するため、自作の設定ファイルでも スキーマを設置すれば補完・型チェックが効きます。

// app.config.json
{
  "$schema": "./app.config.schema.json",
  "port": 3000,
  "logLevel": "info"
}

CIでは ajv validate -s schema.json -d config.json をpre-commitまたはPRチェックに組み込むと、 設定ファイルのtypoがmainにマージされるのを防げます。

よくある落とし穴

実装で使うツール

スキーマを書く前に、対象のサンプルJSONを整形して構造を把握するのが効率的です。JSON Formatter で整形後、 ネストの深さや繰り返し構造を見てからスキーマを設計すると抜けが減ります。 サンプルJSONから型を素早く作りたい場合はJSON to TypeScript で下書きを作り、 それをZodやJSON Schemaに書き換える方が手早いです。

まとめ

JSON Schemaは「データとコードの間の契約書」です。 APIリクエスト・レスポンス・設定ファイルの境界にバリデーション層を1枚置くだけで、 本番障害の相当数を未然に防げます。 ZodやOpenAPIを source of truth にしてスキーマを生成する運用に乗せれば、 型の二重管理コストも避けられます。

関連ツール・ガイド