とほほのJSON Schema入門

目次

JSON Schemaとは

簡単な例

下記のケースでは、オブジェクトは nameage パラメータを持ち、name は文字列型、age は整数型であることを定義しています。どちらも必須プロパティで、未定義の追加プロパティを許可しないことを示しています。

Schema
{
  "type": "object",                 // 全体はオブジェクト型
  "required": ["name", "age"],      // name と age は必須属性
  "additionalProperties": false,    // 未定義の追加プロパティはNG
  "properties": {
    "name": { "type": "string" },   // nameは文字列型
    "age": { "type": "integer" }    // ageは整数型
  }
}
Data
{
  "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

Draft 2019-09

Draft-07

ドキュメント定義

スキーマバージョン($schema)

JSON Schema のバージョンを明確にします。

Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  ...
}

ボキャブラリー($vocabulary)

各スキーマバージョンで定義されている語彙を使用しているか否かを示します。通常はスキーマファイルでひとつだけ記述しますが、複合スキーマドキュメントとして、$id を持つスキーマリソースが複数ある場合はそれぞれに記述することができます。Draft 2019-09 で追加されました。

Schema
{
  "$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)

コメントを記載することができます。

Schema
{
  "name": {
    "type": "string",
    "$comment": "TODO: decide minLength and maxLength"
  }
}

アサーション(制約)

型指定(type)

type には下記いずれか、または下記の配列を指定します。

string          文字列
integer         整数
number          数値
boolean         真偽値
null            null値
array           配列
object          オブジェクト

配列を指定した場合はいずれかの型にマッチすれば OK となります。

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

文字列(string)

文字列型を示します。

Schema
{ "type": "string" }
Data
"ABC"            // OK
123              // NG
""               // OK

整数(integer)

整数型を示します。小数部が指定されていても小数部が 0 であれば OK とみなします。

Schema
{ "type": "integer" }
Data
123              // OK
-123             // OK
12.0             // 小数部が0なのでOK
12.3             // 小数部が0でないのでNG
"123"            // 文字列は数字のみでもNG

数値(number)

浮動小数点数を含めた数値型を示します。

Schema
{ "type": "number" }
Data
123              // OK
12.3             // OK
12.3e4           // OK

真偽値(boolean)

真偽値(true または false) を示します。

Schema
{ "type": "boolean" }
Data
ture             // OK
false            // OK
"ture"           // NG
"1"              // NG

ヌル値(null)

ヌル値(null)を示します。

Schema
{ "type": "null" }
Data
null             // OK
0                // NG
""               // NG

配列(array)

配列([...])を示します。

Schema
{ "type": "array" }
Data
[1, 2, 3]        // OK
["A", "B", "C"]  // OK
[]               // OK

オブジェクト(object)

オブジェクト({...})を示します。

Schema
{ "type": "object" }
Data
{ "name": "Taro" }  // オブジェクトなのでOK
[1, 3, 3, 3, 5]     // オブジェクトではないのでNG

文字列の最小・最大文字数(minLength, maxLength)

値が文字列の場合の最小文字数、最大文字数を指定します。

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

文字列の正規表現パターン(pattern)

値が文字列の場合のパターンを正規表現で指定します。

Schema
{ "type": "string", "pattern": "^[a-zA-Z0-9]{100}$" }

文字列のフォーマット(format)

値が文字列の場合のフォーマットを指定します。下記は E-Mail アドレス形式の文字列を指定しています。どんなフォーマットがサポートされているか、各フォーマットでどのようなバリデーションが行われるかはバリデーションライブラリの実装に依存します。アノテーション(注釈)とみなしてまったく検証しないものもあります。

Schema
{ "type": "string", "format": "email" }

整数倍(multipleOf)

数値が指定した値の整数倍であることを指定します。

Schema
{
  "type": "integer",
  "multipleOf": 100            // 100の整数倍であればOK
}

最小値・最大値(以下・以上)(minimum, maximum)

数値の最小値・最大値を指定します。

Schema
{
  "type": "integer",
  "minimum": 0,                // 0以上であればOK
  "maximum": 100,              // 100以下であればOK
}

最小値・最大値(未満・超過)(exclusiveMinimum, exclusiveMaximum)

数値の最小値・最大値を以下・以上ではなく、未満・超過で指定します。

Schema
{
  "type": "integer",
  "exclusiveMinimum": 0,       // 0より大きければOK   
  "exclusiveMaximum": 100      // 100未満であればOK
}

exclusiveMinimumexclusiveMaximumtrue を指定することにより、minimummaximum の意味を変更することもできます。

Schema
{
  "type": "integer",
  "exclusiveMinimum": true,
  "exclusiveMaximum": true,
  "minimum": 0                 // 0より大きければOK
  "maximum": 100               // 100未満であればOK
}

配列要素の先頭を制限する(prefixItems)

配列要素の先頭要素のスキーマを定義します。

Schema
{
  "type": "array",
  "prefixItems": [
    { "type": "string" },
    { "type": "integer" }
  ]
}
Data
["ABC", 123]        // 型も順序も合っているのでOK
[123, "ABC"]        // 順番が異なるのでNG
["ABC"]             // 後方の省略は許されるのでOK
[123]               // 前方の省略は許されないのでNG
["ABC", 123, true]  // 追加データがあってもOK

配列要素を制限する(items)

配列要素のスキーマを定義します。下記では配列要素が整数であることを示しています。

Schema
{
  "type": "array",
  "items": {
    "type": "integer"
  }
}
Data
[1, 2, 3]        // OK
["A", "B", "C"]  // NG

prefixItems がある場合は、prefixItems で指定した要素に続く要素に対する制約となります。

Schema
{
  "type": "array",
  "prefixItems": [
    { "type": "string" },          // 1個目は文字列
    { "type": "boolean" }          // 2個目は真偽値
  ],
  "items": { "type": "integer" }   // 3個目以降は数値
}
Data
["ABC", true, 1, 2, 3]  // OK

false を指定した場合は、prefixItems で指定した要素に続く要素を許可しません。

Schema
{
  "type": "array",
  "prefixItems": [
    { "type": "string" },          // 1個目は文字列
    { "type": "boolean" }          // 2個目は真偽値
  ],
  "items": false                   // 3個目以降はNG
}
Data
["ABC", true, 1, 2, 3]  // NG

配列要素に含める(contains)

items とほぼ同様ですが、contains の場合は追加要素が少なくとも1個は無ければエラーになる点が異なります。

Schema
{
  "type": "array",
  "prefixItems": [
    { "type": "string" },
    { "type": "boolean" }
  ],
  "contains": { "type": "integer" }
}
Data
["ABC", true, 1]  // 数値をひとつでも含んでいればOK

追加要素の制約(unevaluatedItems)

items と似ていますが、prefixItems, items, contains によって評価されなかった、残りの要素に対する成約かけます。itemsunevaluatedItems の関係は、後述の additionalPropertiesunevaluatedProperties の関係に似ています。Draft 2019-09 で追加されました。

Schema
{
  "type": "array",
  "prefixItems": [
    { "type": "string" },
    { "type": "boolean" }
  ],
  "unevaluatedItems": { "type": "integer" }
}
Data
["ABC", true, 1, 2, 3]        // OK

配列要素の最小数・最大数(minItems, maxItems)

配列に含める要素の最小数・最大数を指定します。

Schema
{
  "type": "array",
  "items": { "type": "integer" },
  "minItems": 2,
  "maxItems": 3
}
Data
[1]             // 要素が1個なのでNG
[1, 2]          // 要素が2個なのでOK
[1, 2, 3]       // 要素が3個なのでOK
[1, 2, 3, 4]    // 要素が4個なのでNG

配列に含める要素の最小数・最大数(minContains, maxContains)

配列に含める要素の中で contains の対象となる要素の最小数・最大数を指定します。Draft 2019-09 で追加されました。

Schema
{
  "type": "array",
  "contains": { "type": "integer" },
  "minContains": 2,
  "maxContains": 3
}
Data
["ABC", 1]          // 整数が1個なのでNG
["ABC", 1, 2]       // 整数が2個なのでOK
["ABC", 1, 2, 3]    // 整数が3個なのでOK
["ABC", 1, 2, 3, 4] // 整数が4個なのでNG

配列要素の重複を制限する(uniqueItems)

配列中に同じ要素が重複して出現しているとエラーとします。

Schema
{
  "type": "array",
  "uniqueItems": true
}
Data
["cat", "dog", "fox"]     // すべての要素が異なっているのでOK
["cat", "dog", "cat"]     // 要素に重複があるのでNG

プロパティ(properties)

このオブジェクトに含まれるプロパティを定義します。

Schema
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  }
}

パターンプロパティ(patternProperties)

プロパティの名前を正規表現で指定します。下記は S: で始まるプロパティは文字列として、I: で始まるプロパティは整数値として処理します。

Schema
{
  "type": "object",
  "patternProperties": {
    "^S:": { "type": "string" },
    "^I:": { "type": "integer" }
  }
}
Data
{
  "S:name": "Tanaka",
  "S:gender": "man",
  "I:age": 26
}

必須プロパティ(required)

デフォルトではプロパティを省略してもエラーとなりませんが、省略を許さない場合は required を指定します。

Schema
{
  "type": "object",
  "required": ["name", "age"],
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer"
    }
  }
}
Data
{
  "name": "Yamada"
                   // 必須プロパティ(age)が無いのでエラー
}

プロパティの最小・最大数(minProperties, maxProperties)

プロパティの数の最小数・最大数を指定します。

Schema
{
  "type": "object",
  "minProperties": 2,
  "maxProperties": 3
}

追加プロパティの制約(additionalProperties)

properties にマッチしない追加プロパティに対する制約を定義します。

Schema
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  },
  "additionalProperties": { "type": "string" }
}
Data
{
  "name": "Yamada",
  "age": 26,
  "gender": "male"  // 追加プロパティも値が文字列であればOK
}

false を指定すると追加プロパティを拒絶します。

Schema
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  },
  "additionalProperties": false
}
Data
{
  "name": "Yamada",
  "age": 26,
  "gender": "male"  // 追加プロパティがあるのでエラー
}

追加プロパティの制約(unevaluatedProperties)

additionalProperties と似ていますが下記の点で異なります。通常は additionalProperties を用いて、サブスキーマの関係でうまく制御できない場合に unevaluatedProperties を使用するのがよさそうです。Draft 2019-09 で追加されました。

additionalPropertiesunevaluatedProperties
対象properties, patternProperties にマッチしなかったプロパティproperties, patternProperties, additionalProperties にマッチしなかったプロパティ
評価タイミングバリデーション中サブスキーマに閉じて評価他のバリデーション終了後にスキーマ全体で評価
使いどころ単純なケースallOf, if, then, else などでサブスキーマを使用する複雑なケース

下記の例では footrue の時だけ baa プロパティを定義しています。additionalProperties だと常に baa がエラーとなります。

Schema
{
  "type": "object",
  "properties": {
    "foo": { "type": "boolean" }
  },
  "required": ["foo"],
  "if": {
    "properties": {
      "foo": { "const": true }
    }
  },
  "then": {
    "properties": {
      "baa": { "type": "string" }
    }
  },
  "unevaluatedProperties": false
}
Data
{ "foo": true, "baa": "..." }    // foo=trueなのでbaaは許される
{ "foo": false, "baa": "..." }   // foo=falseなのでbaaは許されない

プロパティ名の正規表現指定(propertyNames)

プロパティ名に対する制約をかけます。下記の例では、プロパティ名に使用できる文字を a~z、A~Z、0~9 に制限しています。

Schema
{
  "type": "object",
  "propertyNames": {
    "pattern": "^[a-zA-Z0-9]+$"
  }
}

依存必須プロパティ(dependentRequired)

指定したプロパティが存在する場合に要求されるプロパティを指定します。下記の例では foo プロパティが存在する場合は baa プロパティも必須となります。以前は dependencies として実装されていましたが、Draft 2019-09 で dependentRequireddependentSchemas に分離されました。

Schema
{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "baa": { "type": "string" }
  },
  "dependentRequired": {
    "foo": ["baa"]
  }
}

依存スキーマ(dependentSchemas)

指定したプロパティが存在する場合に要求されるスキーマを指定します。下記の例では foo プロパティが存在する場合は baa プロパティも必須となります。dependentRequired ではプロパティの有無しか制御できませんが、もうすこし高度な制約をかけることができます。以前は dependencies として実装されていましたが、Draft 2019-09 で dependentRequireddependentSchemas に分離されました。

Schema
{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "baa": { "type": "string" }
  },
  "dependentSchemas": {
    "foo": { "required": ["baa"] }
  }
}

アノテーション(注釈)

アノテーションはバリデーションに影響を与える訳ではないですが、ドキュメントとして利用者に情報を伝えます。

タイトル(title)

タイトルを示します。

Schema
{
  "$id": "https://example.com/schemas/user",
  "title": "User",
  "description": "System user object."
  ...
}

説明文(description)

説明文を示します。

Schema
{
  "$id": "https://example.com/schemas/user",
  "title": "User",
  "description": "System user object."
  ...
}

例(examples)

例を示します。

Schema
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "example": "foo@example.com"
    }
  }
}

デフォルト値(default)

デフォルト値を示します。

Schema
{
  "type": "object",
  "properties": {
    "size": {
      "enum": ["small", "normal", "big"],
      "default": "normal"
    }
  }
}

読み取り専用(readOnly)

プロパティが読み取り専用であることを示します。

Schema
{
  "type": "object",
  "properties": {
    "user_id": {
      "type": "integer",
      "readOnly": true
    },
    "name": {
      "type": "string"
    }
  }
}

書き込み専用(writeOnly)

プロパティが書込み専用であることを示します。

Schema
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "password": {
      "type": "string",
      "writeOnly": true
    }
  }
}

廃止された(deprecated)

廃止されたことを示します。Draft 2019-09 で追加されました。

Schema
{
  "type": "object",
  "properties": {
    "nickname": {
      "type": "string",
      "deprecated": true
    }
  }
}

コンテントエンコーディング(contentEncoding)

コンテンツのエンコーディングルールを指定します。下記は文字列が BASE64 であることを示します。

Schema
{
  "type": "object",
  "properties": {
    "image": {
      "type": "string",
      "contentEncoding": "base64",
      "contentMediaType": "image/png"
    }
  }
}

コンテントメディアタイプ(contentMediaType)

コンテンツのメディアタイプを指定します。下記は文字列が PNG を BASE64 したものであることを示します。

Schema
{
  "type": "object",
  "properties": {
    "image": {
      "type": "string",
      "contentEncoding": "base64",
      "contentMediaType": "image/png"
    }
  }
}

コンテントスキーマ(contentSchema)

コンテンツのスキーマを指定します。下記の例では style は BASE64 にエンコードされた JSON で、かつ、その JSON は string 型の name プロパティを有していることを示します。Draft 2019-09 で追加されました。

Schema
{
  "type": "object",
  "properties": {
    "style": {
      "type": "string",
      "contentEncoding": "base64",
      "contentMediaType": "application/json",
      "contentSchema": {
        "type": "object",
        "properties": {
          "name": { "type": "string" }
        }
      }
    }
  }
}

列挙型と固定値

列挙型(enum)

列挙した値のいずれかの値をとることを示します。

Schema
{
  "type": "object",
  "properties": {
    "size": {
      "enum": ["small", "normal", "big"]
    }
  }
}

固定値(const)

固定値を示します。固定値以外の値が指定されるとエラーとなります。選択肢がひとつのみの enum とほぼ同義です。

Schema
{
  "type": "object",
  "properties": {
    "version": { "const": "1.0.0" }
  }
}

条件判断

もし(if)

スキーマ定義に「もし(if)~であれば(then)~さもなくば(else)~」といった条件判断を使用することができます。下記のオブジェクトは countrydate のプロパティを持ちます。date は、もし country"USA" であれば MM/DD/YYYY 形式、さもなくば YYYY/MM/DD 形式であることをチェックします。

Schema
{
  "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)

すべてを満たしていれば OK とします(AND)。下記の例では 1 文字以上、10 文字以下の両方を満たしていれば OK とします。

Schema
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "allOf": [
        { "minLength": 1 },
        { "maxLength": 10 }
      ]
    }
  }
}

いずれかを満たしていれば(anyOf)

いずれかを満たしていれば OK とします(OR)。下記の例では agestring または integer 型であれば OK とします。

Schema
{
  "type": "object",
  "properties": {
    "age": {
      "anyOf": [
        { "type": "string" },
        { "type": "integer" }
      ]
    }
  }
}

ひとつのみを満たしていれば(oneOf)

ひとつのみを満たしていれば OK とします(XOR)。あまり実用的な例ではありませんが、下記では "A""B" はどちらか片方のみにマッチするので OK ですが、"C" は両方にマッチするので NG となります。

Schema
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "oneOf": [
        { "pattern": "^[ABC]+$" },
        { "pattern": "^[CDE]+$" }
      ]
    }
  }
}

満たしていなければ(not)

満たしていなければ OK とします(NOT)。下記の例では valuenull 型以外であれば OK となります。

Schema
{
  "type": "object",
  "properties": {
    "value": {
      "not": { "type": "null" }
    }
  }
}

参照

識別子($id)

スキーマに URI を紐づけます。下記の例ではルートスキーマに https://example.com/schemasuser スキーマに https://example.com/schemas/user という URI を紐づけています。この場合、user スキーマは独立したスキーマリソースとみなされます。

Schema
{
  "$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 で追加されました。

Schema
{
  "$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 に改められました。

Schema
{
  "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 で定義したオブジェクトを参照します。

Schema
{
  "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 で定義したアンカー名で指定することもできます。

Schema
{
  "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 で定義したスキーマリソース名で指定することもできます。

Schema
{
  "$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 を参照するようになります。

Schema
{
  "$dynamicAnchor": "node",
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "children": {
      "type": "array",
      "items": { "$dynamicRef": "#node" }
    }
  }
}

ダイナミックリファレンス($dynamicRef)

Draft 2020-12 で追加されました。$dynamicAnchor を参照してください。

様々なケース

プロパティの省略や追加を許さない

required により省略を許さず、additionalProperties により追加を許さないようにします。

Schema
{
  "type": "object",
  "required": ["name", "age"],      // name と age は必須属性
  "additionalProperties": false,    // 追加プロパティを許さない
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  }
}

平仮名であることを検証する

Unicode コードブロックの平仮名(U+3040~U+309F)であることを検証します。長音も含める場合は U+30FC も加えてください。

Schema
{
  "type": "string",
  "pattern": "^[\\u3040-\\u309F]+$"
}

AプロパティがtrueであればBプロパティを必須とする

Schema
{
  "type": "object",
  "properties": {
    "A": { "type": "boolean" },
    "B": { "type": "string" }
  },
  "if": {
    "properties": { "A": { "const": true } }
  },
  "then": {
    "required": ["B"]
  }
}

Aプロパティの値によってBプロパティの選択肢を変更する

Schema
{
  "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"] } }
      }
    }
  ]
}