JSON Schema公共属性引用及未评估属性校验问题咨询
JSON Schema 问题解决:$ref引用失效、未定义属性校验不生效及枚举规则无效
核心问题分析
原Schema的问题根源在于对JSON Schema关键字的使用逻辑错误:
- $ref引用公共属性无效:当在对象定义中同时使用
$ref和同层级的properties、required等关键字时,$ref会完全覆盖这些关键字,导致公共属性(title、occupation)根本没被纳入校验规则。 - unevaluatedProperties: false不生效:子Schema中设置的
additionalProperties: false与顶层的unevaluatedProperties冲突,且allOf组合的子Schema未正确合并属性定义,导致未定义属性(如party_affiliation)无法被拦截。 - occupation枚举校验失效:因为公共属性的定义被
$ref的覆盖逻辑忽略,枚举规则根本没生效。
修正后的JSON Schema
{ "$defs": { "common": { "type": "object", "properties": { "title": { "type": "string" }, "occupation": { "type": "string", "enum": ["Accountant", "Doctor", "Lawyer", "Director"] } } }, "person": { "type": "object", "allOf": [ {"$ref": "#/$defs/common"}, { "required": ["first_name", "last_name", "age"], "properties": { "first_name": {"type": "string"}, "last_name": {"type": "string"}, "age": {"type": "integer"} } } ] }, "employee": { "type": "object", "allOf": [ {"$ref": "#/$defs/common"}, { "properties": { "name": {"type": "string"}, "surname": {"type": "string"}, "age": {"type": "integer"} } } ] }, "football_team": { "type": "object", "allOf": [ {"$ref": "#/$defs/common"}, { "required": ["name", "league"], "properties": { "name": {"type": "string"}, "league": {"type": "string"}, "year_founded": {"type": "integer"}, "replace": {"$ref": "#/$defs/replace"} } } ] }, "replace": { "type": "object", "additionalProperties": false, "properties": { "appt_kind_": {"type": "string"}, "seen_for_": {"type": "string"}, "seen_last_": {"type": "string"}, "specialty_": {"type": "string"} } } }, "allOf": [ {"$ref": "#/$defs/person"}, {"$ref": "#/$defs/football_team"} ], "unevaluatedProperties": false }
关键修改说明
- 用allOf合并公共定义与自身属性:每个需要引用公共属性的对象(person、employee、football_team)都通过
allOf将公共定义和自身的属性、必填规则合并,既实现了代码复用,又避免了$ref覆盖同层级关键字的问题。 - 移除子Schema的additionalProperties: false:统一使用顶层的
unevaluatedProperties: false来限制未定义属性,避免多规则冲突,确保所有未在任何子Schema中定义的属性都会被拦截。 - 确保枚举规则生效:公共属性的枚举定义通过
allOf被正确纳入对象的校验规则,当occupation不在枚举列表中时会直接报错。
验证效果
针对提供的无效JSON示例:
- 包含
party_affiliation或science的实例:会触发unevaluatedProperties: false的校验错误,拦截未定义属性。 occupation: "Master"的实例:会触发枚举校验错误,因为"Master"不在允许的枚举值列表中。
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

