とほほのJSON Schema入門
- JSON Schemaとは
- 簡単な例
- キーワード
- インストール
- JSON Schemaのバージョン
- ドキュメント定義
- コメント
- アサーション(制約)
- 型指定(type)
- 文字列の最小・最大文字数(minLength, maxLength)
- 文字列の正規表現パターン(pattern)
- 文字列のフォーマット(format)
- 整数倍(multipleOf)
- 最小値・最大値(以下・以上)(minimum, maximum)
- 最小値・最大値(未満・超過)(exclusiveMinimum, exclusiveMaximum)
- 配列要素の先頭を制限する(prefixItems)
- 配列要素を制限する(items)
- 配列要素に含める(contains)
- 追加要素の制約(unevaluatedItems)
- 配列要素の最小数・最大数(minItems, maxItems)
- 配列に含める要素の最小数・最大数(minContains, maxContains)
- 配列要素の重複を制限する(uniqueItems)
- プロパティ(properties)
- パターンプロパティ(patternProperties)
- 必須プロパティ(required)
- プロパティの最小・最大数(minProperties, maxProperties)
- 追加プロパティの制約(additionalProperties)
- 追加プロパティの制約(unevaluatedProperties)
- プロパティ名の正規表現指定(propertyNames)
- 依存必須プロパティ(dependentRequired)
- 依存スキーマ(dependentSchemas)
- アノテーション(注釈)
- 列挙型と固定値
- 条件判断
- 論理判断
- 参照
- 様々なケース
- リンク
JSON Schemaとは
- REST API などでやり取りする JSON データのスキーマを定義する言語です。
- 例えば
name
というプロパティを持っていること、その型はstring
型であること、最大文字数は 10 文字以内であることなどのスキーマを定義します。 - スキーマ自体も JSON で定義します。
- ライブラリがスキーマファイルを読み込み、受け取った JSON データをバリデート(検証)することができます。
- キーワードは、アサーション(検証)系とアノテート(注釈)系に分かれます。アサーションはバリデートにより検証し違反があればエラーを返します。アサーションは仕様書ドキュメントとしての意味を持ち、通常は検証されません。
- REST-API 仕様を定義する OpenAPI に採用されています。OpenAPI でやり取りするデータ構造の定義文書として、かつ、バリデーションデータとして利用されています。
簡単な例
下記のケースでは、オブジェクトは name
と age
パラメータを持ち、name
は文字列型、age
は整数型であることを定義しています。どちらも必須プロパティで、未定義の追加プロパティを許可しないことを示しています。
{ "type": "object", // 全体はオブジェクト型 "required": ["name", "age"], // name と age は必須属性 "additionalProperties": false, // 未定義の追加プロパティはNG "properties": { "name": { "type": "string" }, // nameは文字列型 "age": { "type": "integer" } // ageは整数型 } }
{ "name": "Yamada", "age": 26 }
キーワード
$anchor $comment $defs $dynamicAnchor $dynamicRef $id $ref $schema $vocabulary additionalProperties allOf anyOf const contains contentEncoding contentMediaType contentSchema default dependentRequired dependentSchemas deprecated description else enum examples exclusiveMaximum exclusiveMinimum format if items maxContains maximum maxItems maxLength maxProperties minContains minimum minItems minLength minProperties multipleOf not oneOf pattern patternProperties prefixItems properties propertyNames readOnly required then title type unevaluatedItems unevaluatedProperties uniqueItems writeOnly
インストール
Pythonの場合
jsonschema モジュールをインストールします。
pip3 install jsonschema
下記のようなプログラムで検証します。
import json from jsonschema import validate, ValidationError schema = json.loads(""" { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } } """) data = json.loads(""" { "name": "Yamada", "age": 26 } """) try: validate(data, schema) print("OK") except ValidationError as e: print(e)
Perlの場合
cpanm で JSON と JSON::Validator をインストールします。
dnf -y install perl perl-App-cpanminus cpanm JSON JSON::Validator
下記のようなプログラムで検証します。
use JSON; use JSON::Validator; $schema = <<END; { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } } END $data = <<END; { "name": "Yamada", "age": 26 } END my $jv = JSON::Validator->new; $jv->schema(decode_json($schema)); my @errors = $jv->validate(decode_json($data)); if (@errors) { die "@errors" } else { print "OK\n"; }
PHPの場合
composer で justinrainbow/json-schema をインストールします。
composer require justinrainbow/json-schema
下記のようなプログラムで検証します。
<?php require 'vendor/autoload.php'; use JsonSchema\Validator; use JsonSchema\Constraints\Constraint; $schema = json_decode(<<<END { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } } END); $data = json_decode(<<<END { "name": "Yamada", "age": 26 } END); $validator = new Validator(); $validator->validate($data, $schema, Constraint::CHECK_MODE_APPLY_DEFAULTS); if ($validator->isValid()) { echo "OK\n"; } else { foreach ($validator->getErrors() as $error) { echo "- {$error['property']}: {$error['message']}\n"; } }
Node.jsの場合
npm で Ajv(Another JSON Schema Validator)をインストールします。
npm install ajv
下記のようなプログラムで検証します。
const Ajv = require("ajv"); const schema = JSON.parse(` { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } } `); const data = JSON.parse(` { "name": "Yamada", "age": 26 } `); const ajv = new Ajv(); const validate = ajv.compile(schema); if (validate(data)) { console.log("OK"); } else { console.log(validate.errors); }
JSON Schemaのバージョン
Draft 2020-12
"$schema": "https://json-schema.org/draft/2020-12/schema"
items
とadditionalItems
がprefixItems
とitems
キーワードに再デザインされました。$recursiveRef
と$recursiveAnchor
が$dynamicRef
と$dynamicAnchor
に置き換えられました。contains
がunevaluatedItems
に与える影響が仕様化されました。- Unicode への対応を明確化しました。
- スキーマメディアタイプを廃止しました。
- 複合スキーマドキュメントがサポートされ、ひとつのファイルの中に複数のスキーマリソースを定義できるようになりました。それぞれのスキーマリソースには個別の
$id
を割り振ります。 format
がアノテーション(注釈)なのかアサーション(制約)なのか、$vocabulary
で参照する語彙をformat-annotation
とformat-assertion
に分離し、明示できるようにしました。
Draft 2019-09
"$schema": "https://json-schema.org/draft/2019-09/schema"
$vocabulary
が追加されました。$recursiveRef
と$recursiveAnchor
が追加されました。format
の実装にばらつきがあったため、format
はアサーション(注釈)ではなく、アノテーション(注釈)としました。$id
による複数フラグメントを禁止し、代わりに$anchor
による複数アンカーを指定できるようにしました。これにより、ひとつのファイルが複数の URI を持つことはなくなりました。definitions
キーワードが$defs
キーワードに変更されました。dependencies
キーワードが廃止され、dependentSchemas
とdependentRequired
に分離されました。unevaluatedItems
とunevaluatedProperties
が追加されました。maxContains
とminContains
が追加されました。contentSchema
が追加されました。deprecated
が追加されました。
Draft-07
"$schema": "https://json-schema.org/draft-07/schema"
- 2018年3月にリリースされました。
$comment
が追加されました。if
,then
,else
が追加されました。readOnly
が拡張Hyperスキーマからバリデーション仕様に移動し、writeOnly
が追加されました。contentMediaType
とcontentEncoding
が拡張Hyperスキーマからバリデーション仕様に移動しました。
ドキュメント定義
スキーマバージョン($schema)
JSON Schema のバージョンを明確にします。
{ "$schema": "https://json-schema.org/draft/2020-12/schema", ... }
ボキャブラリー($vocabulary)
各スキーマバージョンで定義されている語彙を使用しているか否かを示します。通常はスキーマファイルでひとつだけ記述しますが、複合スキーマドキュメントとして、$id
を持つスキーマリソースが複数ある場合はそれぞれに記述することができます。Draft 2019-09 で追加されました。
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/core": true, "https://json-schema.org/draft/2020-12/vocab/applicator": true, "https://json-schema.org/draft/2020-12/vocab/format-annotation": false }, ... }
語彙には下記などがあります。
.../vocab/core: $id, $schema, $ref などの基本機能 .../vocab/applicator: properties, items, allOf, anyOf, if, then, else などの機能 .../vocab/validation: type, minimum, maxLength などのバリデーション機能 .../vocab/format-annotation: formatをアノテーション(注釈)として使用する .../vocab/format-assertion: formatをアサーション(制約)として使用する
コメント
コメント($comment)
コメントを記載することができます。
{ "name": { "type": "string", "$comment": "TODO: decide minLength and maxLength" } }
アサーション(制約)
型指定(type)
type
には下記いずれか、または下記の配列を指定します。
string 文字列 integer 整数 number 数値 boolean 真偽値 null null値 array 配列 object オブジェクト
配列を指定した場合はいずれかの型にマッチすれば OK となります。
{ "type": ["string", "null"] }
文字列(string)
文字列型を示します。
{ "type": "string" }
"ABC" // OK 123 // NG "" // OK
整数(integer)
整数型を示します。小数部が指定されていても小数部が 0 であれば OK とみなします。
{ "type": "integer" }
123 // OK -123 // OK 12.0 // 小数部が0なのでOK 12.3 // 小数部が0でないのでNG "123" // 文字列は数字のみでもNG
数値(number)
浮動小数点数を含めた数値型を示します。
{ "type": "number" }
123 // OK 12.3 // OK 12.3e4 // OK
真偽値(boolean)
真偽値(true
または false
) を示します。
{ "type": "boolean" }
ture // OK false // OK "ture" // NG "1" // NG
ヌル値(null)
ヌル値(null
)を示します。
{ "type": "null" }
null // OK 0 // NG "" // NG
配列(array)
配列([...]
)を示します。
{ "type": "array" }
[1, 2, 3] // OK ["A", "B", "C"] // OK [] // OK
オブジェクト(object)
オブジェクト({...}
)を示します。
{ "type": "object" }
{ "name": "Taro" } // オブジェクトなのでOK [1, 3, 3, 3, 5] // オブジェクトではないのでNG
文字列の最小・最大文字数(minLength, maxLength)
値が文字列の場合の最小文字数、最大文字数を指定します。
{ "type": "string", "minLength": 1, "maxLength": 100 }
文字列の正規表現パターン(pattern)
値が文字列の場合のパターンを正規表現で指定します。
{ "type": "string", "pattern": "^[a-zA-Z0-9]{100}$" }
文字列のフォーマット(format)
値が文字列の場合のフォーマットを指定します。下記は E-Mail アドレス形式の文字列を指定しています。どんなフォーマットがサポートされているか、各フォーマットでどのようなバリデーションが行われるかはバリデーションライブラリの実装に依存します。アノテーション(注釈)とみなしてまったく検証しないものもあります。
{ "type": "string", "format": "email" }
整数倍(multipleOf)
数値が指定した値の整数倍であることを指定します。
{
"type": "integer",
"multipleOf": 100 // 100の整数倍であればOK
}
最小値・最大値(以下・以上)(minimum, maximum)
数値の最小値・最大値を指定します。
{ "type": "integer", "minimum": 0, // 0以上であればOK "maximum": 100, // 100以下であればOK }
最小値・最大値(未満・超過)(exclusiveMinimum, exclusiveMaximum)
数値の最小値・最大値を以下・以上ではなく、未満・超過で指定します。
{ "type": "integer", "exclusiveMinimum": 0, // 0より大きければOK "exclusiveMaximum": 100 // 100未満であればOK }
exclusiveMinimum
や exclusiveMaximum
に true
を指定することにより、minimum
や maximum
の意味を変更することもできます。
{ "type": "integer", "exclusiveMinimum": true, "exclusiveMaximum": true, "minimum": 0 // 0より大きければOK "maximum": 100 // 100未満であればOK }
配列要素の先頭を制限する(prefixItems)
配列要素の先頭要素のスキーマを定義します。
{ "type": "array", "prefixItems": [ { "type": "string" }, { "type": "integer" } ] }
["ABC", 123] // 型も順序も合っているのでOK [123, "ABC"] // 順番が異なるのでNG ["ABC"] // 後方の省略は許されるのでOK [123] // 前方の省略は許されないのでNG ["ABC", 123, true] // 追加データがあってもOK
配列要素を制限する(items)
配列要素のスキーマを定義します。下記では配列要素が整数であることを示しています。
{ "type": "array", "items": { "type": "integer" } }
[1, 2, 3] // OK ["A", "B", "C"] // NG
prefixItems
がある場合は、prefixItems
で指定した要素に続く要素に対する制約となります。
{ "type": "array", "prefixItems": [ { "type": "string" }, // 1個目は文字列 { "type": "boolean" } // 2個目は真偽値 ], "items": { "type": "integer" } // 3個目以降は数値 }
["ABC", true, 1, 2, 3] // OK
false
を指定した場合は、prefixItems
で指定した要素に続く要素を許可しません。
{ "type": "array", "prefixItems": [ { "type": "string" }, // 1個目は文字列 { "type": "boolean" } // 2個目は真偽値 ], "items": false // 3個目以降はNG }
["ABC", true, 1, 2, 3] // NG
配列要素に含める(contains)
items
とほぼ同様ですが、contains
の場合は追加要素が少なくとも1個は無ければエラーになる点が異なります。
{ "type": "array", "prefixItems": [ { "type": "string" }, { "type": "boolean" } ], "contains": { "type": "integer" } }
["ABC", true, 1] // 数値をひとつでも含んでいればOK
追加要素の制約(unevaluatedItems)
items
と似ていますが、prefixItems
, items
, contains
によって評価されなかった、残りの要素に対する成約かけます。items
と unevaluatedItems
の関係は、後述の additionalProperties
と unevaluatedProperties
の関係に似ています。Draft 2019-09 で追加されました。
{ "type": "array", "prefixItems": [ { "type": "string" }, { "type": "boolean" } ], "unevaluatedItems": { "type": "integer" } }
["ABC", true, 1, 2, 3] // OK
配列要素の最小数・最大数(minItems, maxItems)
配列に含める要素の最小数・最大数を指定します。
{ "type": "array", "items": { "type": "integer" }, "minItems": 2, "maxItems": 3 }
[1] // 要素が1個なのでNG [1, 2] // 要素が2個なのでOK [1, 2, 3] // 要素が3個なのでOK [1, 2, 3, 4] // 要素が4個なのでNG
配列に含める要素の最小数・最大数(minContains, maxContains)
配列に含める要素の中で contains
の対象となる要素の最小数・最大数を指定します。Draft 2019-09 で追加されました。
{ "type": "array", "contains": { "type": "integer" }, "minContains": 2, "maxContains": 3 }
["ABC", 1] // 整数が1個なのでNG ["ABC", 1, 2] // 整数が2個なのでOK ["ABC", 1, 2, 3] // 整数が3個なのでOK ["ABC", 1, 2, 3, 4] // 整数が4個なのでNG
配列要素の重複を制限する(uniqueItems)
配列中に同じ要素が重複して出現しているとエラーとします。
{ "type": "array", "uniqueItems": true }
["cat", "dog", "fox"] // すべての要素が異なっているのでOK ["cat", "dog", "cat"] // 要素に重複があるのでNG
プロパティ(properties)
このオブジェクトに含まれるプロパティを定義します。
{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } }
パターンプロパティ(patternProperties)
プロパティの名前を正規表現で指定します。下記は S:
で始まるプロパティは文字列として、I:
で始まるプロパティは整数値として処理します。
{ "type": "object", "patternProperties": { "^S:": { "type": "string" }, "^I:": { "type": "integer" } } }
{ "S:name": "Tanaka", "S:gender": "man", "I:age": 26 }
必須プロパティ(required)
デフォルトではプロパティを省略してもエラーとなりませんが、省略を許さない場合は required
を指定します。
{ "type": "object", "required": ["name", "age"], "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } }
{
"name": "Yamada"
// 必須プロパティ(age)が無いのでエラー
}
プロパティの最小・最大数(minProperties, maxProperties)
プロパティの数の最小数・最大数を指定します。
{ "type": "object", "minProperties": 2, "maxProperties": 3 }
追加プロパティの制約(additionalProperties)
properties
にマッチしない追加プロパティに対する制約を定義します。
{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, "additionalProperties": { "type": "string" } }
{
"name": "Yamada",
"age": 26,
"gender": "male" // 追加プロパティも値が文字列であればOK
}
false
を指定すると追加プロパティを拒絶します。
{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, "additionalProperties": false }
{
"name": "Yamada",
"age": 26,
"gender": "male" // 追加プロパティがあるのでエラー
}
追加プロパティの制約(unevaluatedProperties)
additionalProperties と似ていますが下記の点で異なります。通常は additionalProperties
を用いて、サブスキーマの関係でうまく制御できない場合に unevaluatedProperties
を使用するのがよさそうです。Draft 2019-09 で追加されました。
additionalProperties | unevaluatedProperties | |
---|---|---|
対象 | properties , patternProperties にマッチしなかったプロパティ | properties , patternProperties , additionalProperties にマッチしなかったプロパティ |
評価タイミング | バリデーション中サブスキーマに閉じて評価 | 他のバリデーション終了後にスキーマ全体で評価 |
使いどころ | 単純なケース | allOf , if , then , else などでサブスキーマを使用する複雑なケース |
下記の例では foo
が true
の時だけ baa
プロパティを定義しています。additionalProperties
だと常に baa
がエラーとなります。
{ "type": "object", "properties": { "foo": { "type": "boolean" } }, "required": ["foo"], "if": { "properties": { "foo": { "const": true } } }, "then": { "properties": { "baa": { "type": "string" } } }, "unevaluatedProperties": false }
{ "foo": true, "baa": "..." } // foo=trueなのでbaaは許される { "foo": false, "baa": "..." } // foo=falseなのでbaaは許されない
プロパティ名の正規表現指定(propertyNames)
プロパティ名に対する制約をかけます。下記の例では、プロパティ名に使用できる文字を a~z、A~Z、0~9 に制限しています。
{ "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9]+$" } }
依存必須プロパティ(dependentRequired)
指定したプロパティが存在する場合に要求されるプロパティを指定します。下記の例では foo
プロパティが存在する場合は baa
プロパティも必須となります。以前は dependencies
として実装されていましたが、Draft 2019-09 で dependentRequired
と dependentSchemas
に分離されました。
{ "type": "object", "properties": { "foo": { "type": "string" }, "baa": { "type": "string" } }, "dependentRequired": { "foo": ["baa"] } }
依存スキーマ(dependentSchemas)
指定したプロパティが存在する場合に要求されるスキーマを指定します。下記の例では foo
プロパティが存在する場合は baa
プロパティも必須となります。dependentRequired
ではプロパティの有無しか制御できませんが、もうすこし高度な制約をかけることができます。以前は dependencies
として実装されていましたが、Draft 2019-09 で dependentRequired
と dependentSchemas
に分離されました。
{ "type": "object", "properties": { "foo": { "type": "string" }, "baa": { "type": "string" } }, "dependentSchemas": { "foo": { "required": ["baa"] } } }
アノテーション(注釈)
アノテーションはバリデーションに影響を与える訳ではないですが、ドキュメントとして利用者に情報を伝えます。
タイトル(title)
タイトルを示します。
{ "$id": "https://example.com/schemas/user", "title": "User", "description": "System user object." ... }
説明文(description)
説明文を示します。
{ "$id": "https://example.com/schemas/user", "title": "User", "description": "System user object." ... }
例(examples)
例を示します。
{ "type": "object", "properties": { "email": { "type": "string", "example": "foo@example.com" } } }
デフォルト値(default)
デフォルト値を示します。
{ "type": "object", "properties": { "size": { "enum": ["small", "normal", "big"], "default": "normal" } } }
読み取り専用(readOnly)
プロパティが読み取り専用であることを示します。
{ "type": "object", "properties": { "user_id": { "type": "integer", "readOnly": true }, "name": { "type": "string" } } }
書き込み専用(writeOnly)
プロパティが書込み専用であることを示します。
{ "type": "object", "properties": { "name": { "type": "string" }, "password": { "type": "string", "writeOnly": true } } }
廃止された(deprecated)
廃止されたことを示します。Draft 2019-09 で追加されました。
{ "type": "object", "properties": { "nickname": { "type": "string", "deprecated": true } } }
コンテントエンコーディング(contentEncoding)
コンテンツのエンコーディングルールを指定します。下記は文字列が BASE64 であることを示します。
{ "type": "object", "properties": { "image": { "type": "string", "contentEncoding": "base64", "contentMediaType": "image/png" } } }
コンテントメディアタイプ(contentMediaType)
コンテンツのメディアタイプを指定します。下記は文字列が PNG を BASE64 したものであることを示します。
{ "type": "object", "properties": { "image": { "type": "string", "contentEncoding": "base64", "contentMediaType": "image/png" } } }
コンテントスキーマ(contentSchema)
コンテンツのスキーマを指定します。下記の例では style
は BASE64 にエンコードされた JSON で、かつ、その JSON は string
型の name
プロパティを有していることを示します。Draft 2019-09 で追加されました。
{ "type": "object", "properties": { "style": { "type": "string", "contentEncoding": "base64", "contentMediaType": "application/json", "contentSchema": { "type": "object", "properties": { "name": { "type": "string" } } } } } }
列挙型と固定値
列挙型(enum)
列挙した値のいずれかの値をとることを示します。
{ "type": "object", "properties": { "size": { "enum": ["small", "normal", "big"] } } }
固定値(const)
固定値を示します。固定値以外の値が指定されるとエラーとなります。選択肢がひとつのみの enum
とほぼ同義です。
{ "type": "object", "properties": { "version": { "const": "1.0.0" } } }
条件判断
もし(if)
スキーマ定義に「もし(if)~であれば(then)~さもなくば(else)~」といった条件判断を使用することができます。下記のオブジェクトは country
と date
のプロパティを持ちます。date
は、もし country
が "USA"
であれば MM/DD/YYYY
形式、さもなくば YYYY/MM/DD
形式であることをチェックします。
{ "type": "object", "properties": { "country": { "enum": ["USA", "Japan"] }, "date": { "type": "string" } }, "if": { "properties": { "country": { "const": "USA" } } }, "then": { "properties": { "date": { "pattern": "^[0-9]{2}/[0-9]{2}/[0-9]{4}$" } } }, "else": { "properties": { "date": { "pattern": "^[0-9]{4}/[0-9]{2}/[0-9]{2}$" } } } }
であれば(then)
使用例は もし(if) を参照してください。
さもなくば(else)
使用例は もし(if) を参照してください。JSON Schema では else-if はサポートされていません。ネストを深くして対応する方法もありますが、allOf
を用いて switch 文のように記述することもできます。後述の「Aプロパティの値によってBプロパティの選択肢を変更する」の例を参照してください。
論理判断
下記の論理判断を行うことができます。
allOf
: すべてが真であれば(AND)anyOf
: いずれかが真であれば(OR)oneOf
: どれかひとつのみ真であれば(XOR)not
: 真でなければ(NOT)
すべてを満たしていれば(allOf)
すべてを満たしていれば OK とします(AND)。下記の例では 1 文字以上、10 文字以下の両方を満たしていれば OK とします。
{ "type": "object", "properties": { "name": { "type": "string", "allOf": [ { "minLength": 1 }, { "maxLength": 10 } ] } } }
いずれかを満たしていれば(anyOf)
いずれかを満たしていれば OK とします(OR)。下記の例では age
が string
または integer
型であれば OK とします。
{ "type": "object", "properties": { "age": { "anyOf": [ { "type": "string" }, { "type": "integer" } ] } } }
ひとつのみを満たしていれば(oneOf)
ひとつのみを満たしていれば OK とします(XOR)。あまり実用的な例ではありませんが、下記では "A"
や "B"
はどちらか片方のみにマッチするので OK ですが、"C"
は両方にマッチするので NG となります。
{ "type": "object", "properties": { "name": { "type": "string", "oneOf": [ { "pattern": "^[ABC]+$" }, { "pattern": "^[CDE]+$" } ] } } }
満たしていなければ(not)
満たしていなければ OK とします(NOT)。下記の例では value
が null
型以外であれば OK となります。
{ "type": "object", "properties": { "value": { "not": { "type": "null" } } } }
参照
識別子($id)
スキーマに URI を紐づけます。下記の例ではルートスキーマに https://example.com/schemas
、user
スキーマに https://example.com/schemas/user
という URI を紐づけています。この場合、user
スキーマは独立したスキーマリソースとみなされます。
{ "$id": "https://example.com/schemas", "$defs": { "user": { "$id": "/schemas/user", "type": "object", "properties": { ... } ...
アンカー($anchor)
スキーマにアンカー名(#...
)を紐づけます。下記の例では user
スキーマに https://example.com/schemas#user
という URI+アンカーを紐づけています。この場合、user
スキーマはルートスキーマの一部と見なされます。Draft 2019-09 で追加されました。
{ "$id": "https://example.com/schemas", "$defs": { "user": { "$anchor": "user", "type": "object", "properties": { ... } ...
定義($defs)
$defs
で定義したオブジェクトが $ref
で参照されます。下記の例では created_by
にも modified_by
にも同じ型、最小文字数、最大文字数が適用されます。Draft-07 までは definitions
というキーワードでしたが、Draft 2019-09 で $defs
に改められました。
{ "type": "object", "properties": { "created_by": { "$ref": "#/$defs/user_name" }, "modified_by": { "$ref": "#/$defs/user_name" } }, "$defs": { "user_name": { "type": "string", "minLength": 1, "maxLength": 30 } } }
参照($ref)
$defs
で定義したオブジェクトを参照します。
{ "type": "object", "properties": { "created_by": { "$ref": "#/$defs/user_name" }, "modified_by": { "$ref": "#/$defs/user_name" } }, "$defs": { "user_name": { "type": "string", "minLength": 1, "maxLength": 30 } } }
$anchor
で定義したアンカー名で指定することもできます。
{ "type": "object", "properties": { "created_by": { "$ref": "#user_name" }, "modified_by": { "$ref": "#user_name" } }, "$defs": { "user_name": { "$anchor": "user_name", "type": "string", "minLength": 1, "maxLength": 30 } } }
$id
で定義したスキーマリソース名で指定することもできます。
{ "$id": "https://example.com/schemas", "type": "object", "properties": { "created_by": { "$ref": "https://example.com/schemas/user_name" }, "modified_by": { "$ref": "https://example.com/schemas/user_name" } }, "$defs": { "user_name": { "$id": "/schemas/user_name", "type": "string", "minLength": 1, "maxLength": 30 } } }
ダイナミックアンカー($dynamicAnchor)
Draft 2020-12 で追加されました。$anchor
と似ていますが、$anchor
がスキーマ読込時に解決され、再定義できず、通常の参照に利用されるのに対し、$dynamicAnchor
はバリデーション実行時に解決されることで再定義を可能とし、再帰・継承・メタスキーマなどに利用されます。下記は node
が多重階層となる構造で、3階層目の #node
は2階層目で再定義された #node
を参照するようになります。
{ "$dynamicAnchor": "node", "type": "object", "properties": { "name": { "type": "string" }, "children": { "type": "array", "items": { "$dynamicRef": "#node" } } } }
ダイナミックリファレンス($dynamicRef)
Draft 2020-12 で追加されました。$dynamicAnchor を参照してください。
様々なケース
プロパティの省略や追加を許さない
required
により省略を許さず、additionalProperties
により追加を許さないようにします。
{ "type": "object", "required": ["name", "age"], // name と age は必須属性 "additionalProperties": false, // 追加プロパティを許さない "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } }
平仮名であることを検証する
Unicode コードブロックの平仮名(U+3040~U+309F)であることを検証します。長音も含める場合は U+30FC も加えてください。
{ "type": "string", "pattern": "^[\\u3040-\\u309F]+$" }
AプロパティがtrueであればBプロパティを必須とする
{ "type": "object", "properties": { "A": { "type": "boolean" }, "B": { "type": "string" } }, "if": { "properties": { "A": { "const": true } } }, "then": { "required": ["B"] } }
Aプロパティの値によってBプロパティの選択肢を変更する
{ "type": "object", "properties": { "A": { "enum": ["fruit", "animal"] }, "B": { "type": "string" } }, "allOf": [ { "if": { "properties": { "A": { "const": "fruit" } } }, "then": { "properties": { "B": { "enum": ["apple", "banana", "orange"] } } } }, { "if": { "properties": { "A": { "const": "animal" } } }, "then": { "properties": { "B": { "enum": ["cat", "dog", "fox"] } } } } ] }