如何设计可复用公共属性、验证两类重叠对象的JSON Schema?
复用公共属性实现JSON Schema分支验证
你可以通过两种方式解决这个问题,既复用公共属性规则,又实现预期的验证逻辑:
方法一:使用$defs抽离公共属性(兼容旧版JSON Schema)
将公共属性规则抽离到$defs中,在每个oneOf分支里通过allOf引用公共规则,同时在分支内设置additionalProperties: false,这样既保证公共属性被复用,又限制每个分支只能包含公共属性+分支专属属性:
{ "$defs": { "common": { "properties": { "a": {"const": 1} }, "required": ["a"] } }, "oneOf": [ { "allOf": [{"$ref": "#/$defs/common"}], "properties": { "b": {"const": 2} }, "required": ["b"], "additionalProperties": false }, { "allOf": [{"$ref": "#/$defs/common"}], "properties": { "c": {"const": 3} }, "required": ["c"], "additionalProperties": false } ] }
方法二:使用unevaluatedProperties(JSON Schema Draft 2019-09+)
如果你的验证环境支持Draft 2019-09或更高版本,可以用unevaluatedProperties: false替代additionalProperties: false。它会识别所有通过oneOf等关键字定义的属性,不会把分支里的b或c判定为额外属性,写法更接近你最初的需求:
{ "properties": { "a": {"const": 1} }, "required": ["a"], "oneOf": [ { "properties": {"b": {"const": 2}}, "required": ["b"] }, { "properties": {"c": {"const": 3}}, "required": ["c"] } ], "unevaluatedProperties": false }
原理说明
- 最初的Schema验证失败,是因为
additionalProperties: false只作用于当前层级定义的properties(即仅允许a),但oneOf要求对象包含b或c,两者冲突。 unevaluatedProperties会检查所有被Schema评估过的属性(包括oneOf分支里定义的属性),因此不会把b/c当成非法的额外属性。- 用
$defs抽离公共属性的方式,通过allOf合并公共规则和分支规则,再在分支内限制额外属性,完美解决了复用和规则冲突的问题。
内容的提问来源于stack exchange,提问作者Joseph Summerhays
相关产品推荐
相关产品推荐

