JSON Schemaには,oneOf
という便利な構文が用意されている。これは,与えられたスキーマのうちどれか1つだけがvalidなときvalidとする構文だ。
さて,そのoneOf
の挙動で困ったのでメモする。具体的には,オブジェクト型Aと,別のオブジェクト型B,そしてAとBとをallOf
でマージしたABとがあるとき,AとBとABとのoneOf
を構成することができないのだ。
例として以下にスキーマを示す。このスキーマ自体はvalidだが,実は#ab
を許容できない。
{ "definitions": { "a": { "$id": "#a", "additionalProperties": true, "type": "object", "required": ["a"], "properties": { "a": { "type": "number" } } }, "b": { "$id": "#b", "additionalProperties": true, "type": "object", "required": ["b"], "properties": { "b": { "type": "number" } } }, "ab": { "$id": "#ab", "additionalProperties": false, "properties": { "a": {}, "b": {} }, "allOf": [{ "$ref": "#a" }, { "$ref": "#b" }] } }, "$schema": "http://json-schema.org/draft-07/schema#", "oneOf": [{ "$ref": "#a" }, { "$ref": "#b" }, { "$ref": "#ab" }] }
oneOf
の挙動
どうして#ab
を許容しないかというと,oneOf
の挙動にもとづいている。oneOf
は,「与えられたスキーマでJSONをvalidateしていき,どれか1つのスキーマにだけvalidなときにvalidになる」構文だ。この例では,#a
か#b
か#ab
のうち,いずれか1つだけがvalidにならなければならない。
しかしながら,#ab
に対してvalidなJSONは#a
にも#b
にもvalidになってしまう(allOf
で制約を満たしているのだから当然だが)ので,いずれか1つだけのスキーマにvalidになることができない。
大抵の場合,本当に欲しいのはoneOf
ではなく,「どれかにマッチする(anyOf
)」なので,そう置換する。