ブログ

JSON Schema入門:データ構造の定義とバリデーション

JSONは本質的に柔軟です。どのキーにどんな値でも入れられ、構造を強制する仕組みが組み込まれていません。この柔軟性はプロトタイピングには便利ですが、特定のフィールド・型・制約を期待する本番システムでは危険です。JSON Schemaは、有効なJSONの形を宣言的な言語で記述することでこの問題を解決します。

JSON Schemaとは?

JSON Schemaは、JSONドキュメントにアノテーションを付けてバリデーションするためのボキャブラリです。スキーマ自体もJSONで書かれているため、読み書きしやすく、ツールチェインへの組み込みも容易です。現在の安定した仕様はDraft 2020-12で、json-schema.orgでメンテナンスされています。

スキーマはJSON値の期待される形を記述します。バリデーターはスキーマを使って、指定されたドキュメントが準拠しているかを確認し、準拠していない場合はどの制約がどこで違反されたかを正確に報告します。

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}

このスキーマは、nameという文字列フィールドを持つすべてのオブジェクトを受け入れます。ageフィールドは省略可能ですが、存在する場合は非負の整数でなければなりません。

基本的な型定義

JSON SchemaはJSONの6つのネイティブ型に直接対応しています。

string

{ "type": "string" }

任意のJSON文字列値にマッチします。最小・最大長の制約を追加できます。

{
"type": "string",
"minLength": 1,
"maxLength": 100
}

numberとinteger

{ "type": "number" }
{ "type": "integer" }

numberは整数と浮動小数点数の両方を受け入れます。integerは整数のみを受け入れます。minimummaximumexclusiveMinimumexclusiveMaximumで範囲制約を追加できます。

{
"type": "number",
"minimum": 0,
"maximum": 1
}

boolean

{ "type": "boolean" }

trueまたはfalseのみにマッチします。

null

{ "type": "null" }

JSONのnull値のみにマッチします。配列を使って別の型と組み合わせることが多いです。

{ "type": ["string", "null"] }

object

{
"type": "object",
"properties": {
"id": { "type": "integer" },
"email": { "type": "string" }
}
}

propertiesキーワードは名前付きフィールドを定義します。デフォルトではすべてのプロパティは省略可能です。

array

{
"type": "array",
"items": { "type": "string" }
}

itemsキーワードはすべての要素の型を制約します。minItemsmaxItemsで長さを制御できます。

必須フィールドと省略可能フィールド

オブジェクトスキーマのすべてのプロパティはデフォルトで省略可能です。requiredキーワードを使って存在を強制します。

{
"type": "object",
"properties": {
"username": { "type": "string" },
"email": { "type": "string" },
"bio": { "type": "string" }
},
"required": ["username", "email"]
}

ここではusernameemailが必須です。bioは省略可能です。requiredpropertiesの中ではなく、その兄弟として配置することに注意してください。

未知のプロパティを完全に禁止するには、"additionalProperties": falseを追加します。

{
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" }
},
"required": ["id", "name"],
"additionalProperties": false
}

高度な機能

enum

値を固定された許可オプションのセットに制限します。

{
"type": "string",
"enum": ["draft", "published", "archived"]
}

enumは型をまたいで機能します。同じリストに任意のJSON型の特定の値を列挙できます。

pattern

正規表現で文字列をバリデーションします。

{
"type": "string",
"pattern": "^[a-z0-9_-]{3,30}$"
}

スラッグ、ユーザー名、識別子、予測可能なフォーマットを持つ任意の文字列に便利です。

format

一般的な文字列フォーマットのセマンティックバリデーションを提供します。

{ "type": "string", "format": "email" }
{ "type": "string", "format": "date" }
{ "type": "string", "format": "uri" }
{ "type": "string", "format": "uuid" }

注意:formatバリデーションは仕様ではオプションです。デフォルトで強制するバリデーターもあれば、明示的な設定が必要なものもあります。

minimumとmaximum

数値について説明しましたが、integerにも適用されることは特筆に値します。

{
"type": "integer",
"minimum": 1,
"maximum": 100
}

$refとスキーマ合成

$refは別のスキーマ定義を参照でき、再利用と重複回避を可能にします。

{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string" }
},
"required": ["street", "city", "country"]
}
},
"type": "object",
"properties": {
"billing": { "$ref": "#/$defs/address" },
"shipping": { "$ref": "#/$defs/address" }
}
}

スキーマの合成にはallOfanyOfoneOfnotを使用します。

キーワード意味
allOf列挙されたすべてのスキーマに対して有効でなければならない
anyOf少なくとも1つのスキーマに対して有効でなければならない
oneOf正確に1つのスキーマに対して有効でなければならない
not指定されたスキーマに対して有効であってはならない

実践的な活用方法

APIドキュメント

JSON SchemaはOpenAPI(旧Swagger)の基盤です。OpenAPI仕様のすべてのリクエストボディとレスポンスボディはJSON Schemaで記述されます。スキーマを書くことで暗黙的な前提を明示化でき、ドキュメントの品質とクライアントコードの信頼性が向上します。

フォーム生成

react-jsonschema-formjsonformsなどのライブラリはJSON Schemaを読み込み、組み込みバリデーション付きのフォームUIを自動生成します。1つのスキーマ定義がバックエンドのバリデーションとフロントエンドのレンダリング両方を駆動します。

コードでのデータバリデーション

ほとんどの言語に成熟したJSON Schemaバリデーターライブラリがあります。

// JavaScript — ajv
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) console.log(validate.errors);
# Python — jsonschema
from jsonschema import validate, ValidationError
try:
validate(instance=data, schema=schema)
except ValidationError as e:
print(e.message)

CIパイプラインでのバリデーション

コミットフックやCIステップでJSONの設定ファイルをスキーマに対して自動バリデーションすることで、構造的なエラーが本番に届く前に検出できます。

JSONKitのスキーマツールを使う

JSONKitのSchemaツールはJSON Schemaを操作するためのインタラクティブな環境を提供します。

  • JSONスキーマとJSONドキュメントを並べて貼り付け
  • バリデーションを即座に実行し、フィールドごとのエラーメッセージを確認
  • 既存のJSONドキュメントからスターターとなるスキーマを生成
  • allOfanyOf$refを使ったスキーマ合成を探索

JSONからスキーマを生成する機能は、既存のデータセットがあってそれを記述するスキーマを素早く作りたい場合に特に便利です。

まとめ

JSON Schemaは、コンパイル手順や特定のプログラミング言語を必要とせずに、JSONデータに型安全性と構造的な契約をもたらします。サービス間、チーム間、フロントエンドとバックエンドの間というプロトコルレベルで機能するため、開発者のデータバリデーションツールキットの中で最も広く適用できるツールの1つです。まずシンプルな型定義と必須フィールドから始め、データモデルが成熟するにつれてpatternenum$refなどの制約を重ねていきましょう。