共通部分の切り出し
definitions
というブロックに指定した値はproperties
の各設定で使い回すことができます。
例えば以下は URL の設定を期待するプロパティが2つあるスキーマの例です。(ルートのtitle
などは省略)
ちなみにpattern
は文字列のパターンにマッチしたものだけに絞ることができるプロパティです。
{
"type": "object",
"properties": {
"link": {
"type": "string",
"pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
},
"iconLink": {
"type": "string",
"pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
},
}
}
ただこのパターンを覚えるのは厳しいので、同じようなプロパティを追加しなければいけなくなった時にコピペして使う他ありません。ただそれも、スキーマの定義部分がぱっと見複雑そうな構造になってしまいます。
このような場合はdefinitions
プロパティをルートに定義します。
definitions
例えばこのようにしてみます。
{
"definitions": {
"pattern": {
"url": {
"type": "string",
"pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
}
},
}
}
このdefinitions
以下で定義した値は、properties
の各プロパティでベース(JavaScriptでのObject.assign
)のように使うことができます。それには$ref
というプロパティに#
(ルート)からのパスを指定するだけです。子のパス参照は.
ではなく/
を使います。
{
"type": "object",
"properties": {
"link": {
"$ref": "#/definitions/pattern/url"
},
"iconLink": {
"$ref": "#/definitions/pattern/url",
"description": "`description`設定をこちらだけ追加する"
},
}
}
これで先ほどよりはスッキリ記述することができました。
$id を使ってさらに短く
definitions
に$id
を指定すると#/definitions/path/to
と長いパスを置かなくても、$ref
にその名前を設定するだけで同じ意味になります。
{
"definitions": {
"pattern": {
"url": {
"$id": "#urlPattern",
"type": "string",
"pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
}
}
}
}
使うと
{
"type": "object",
"properties": {
"link": {
"$ref": "#urlPattern"
},
}
}
別ファイルの definitions を使う
例えば.json
ファイルが大きくなってきたので同じ階層にdefinitions.json
というファイルを作りdefinitions
プロパティを分割したとします。その時は#/
の前にその読み込みたいファイルまでの相対パスを書いて上げると#/
以降のパスは分割先のパスを見るようになります。
{
"type": "object",
"properties": {
"link": {
"$ref": "./definitions.json#/definitions/pattern/url"
},
}
}