JSON Schema子模式条件验证问题排查与解决
JSON Schema条件验证失效问题:分析与修复
问题背景
我定义了Actor的JSON Schema,期望根据父对象的actor_category枚举值(EMP/MANAGER),对actor_metadata字段应用对应子模式:
- 当
actor_category为EMP时,actor_metadata需符合EmpSchema - 当
actor_category为MANAGER时,actor_metadata需符合ManagerSchema
但当前Schema错误地通过了不符合要求的测试Payload,需要找出问题并修复。
原定义Schema
{ "$schema": "http://json-schema.org/draft-07/schema", "title": "Actor", "type": "object", "additionalProperties": false, "properties": { "actor_id": { "title": "actor_id", "description": "actor unique id", "type": "string" }, "actor_category": { "title": "actor_category", "description": "actor category", "enum": [ "EMP", "MANAGER" ] }, "actor_metadata": { "title": "actor_metadata", "description": "actor metadata json", "oneOf": [ { "if": { "properties": { "actor_category": { "const": "EMP" } } }, "then": { "$ref": "#/definitions/EmpSchema" } }, { "if": { "properties": { "actor_category": { "const": "MANAGER" } } }, "then": { "$ref": "#/definitions/ManagerSchema" } } ] } }, "definitions": { "EmpSchema": { "title": "Employee", "type": "object", "additionalProperties": false, "properties": { "emp_uuid": { "title": "emp_uuid", "description": "emp-uuid, default actor", "type": "string", "format": "uuid" } }, "required": [ "emp_uuid" ] }, "ManagerSchema": { "title": "Manager", "type": "object", "additionalProperties": false, "properties": { "manager_uuid": { "title": "manager_uuid", "description": "manager-uuid", "type": "string", "format": "uuid" }, "manager_dept": { "title": "manager_dept", "description": "manager department", "type": "string" } }, "required": [ "manager_uuid", "manager_dept" ] } }, "required": [ "actor_id", "actor_category", "actor_metadata" ] }
问题Payload
{ "actor_id": "XYZ-123", "actor_category": "MANAGER", "actor_metadata": { "emp_uuid": "be93dfd1-5bda-42fc-86b1-1166481ddac8" } }
问题根源
问题出在你把if/then逻辑放在了actor_metadata字段的oneOf数组里,这会导致两个关键问题:
- 作用域错误:
if条件里的actor_category是在actor_metadata对象内部查找,而不是父对象的actor_category。因为当前if处于actor_metadata的子Schema中,默认作用域是当前字段,根本找不到父对象的属性,所以if条件永远不成立,then约束完全不会生效。 oneOf逻辑失效:由于两个if条件都不触发,JSON Schema会认为这两个子Schema都满足(if不成立时,整个if/then语句对实例是兼容的),导致oneOf只要有一个满足就通过,而实际上两个约束都没起作用,所以任何actor_metadata都会被允许。
修复方案
需要把if/then逻辑提升到父对象级别,让if能正确引用根对象的actor_category属性,同时直接约束actor_metadata的格式。
修正后的Schema
{ "$schema": "http://json-schema.org/draft-07/schema", "title": "Actor", "type": "object", "additionalProperties": false, "properties": { "actor_id": { "title": "actor_id", "description": "actor unique id", "type": "string" }, "actor_category": { "title": "actor_category", "description": "actor category", "enum": ["EMP", "MANAGER"] }, "actor_metadata": { "title": "actor_metadata", "description": "actor metadata json", "type": "object" } }, "definitions": { "EmpSchema": { "title": "Employee", "type": "object", "additionalProperties": false, "properties": { "emp_uuid": { "title": "emp_uuid", "description": "emp-uuid, default actor", "type": "string", "format": "uuid" } }, "required": ["emp_uuid"] }, "ManagerSchema": { "title": "Manager", "type": "object", "additionalProperties": false, "properties": { "manager_uuid": { "title": "manager_uuid", "description": "manager-uuid", "type": "string", "format": "uuid" }, "manager_dept": { "title": "manager_dept", "description": "manager department", "type": "string" } }, "required": ["manager_uuid", "manager_dept"] } }, "required": ["actor_id", "actor_category", "actor_metadata"], "oneOf": [ { "if": { "properties": { "actor_category": { "const": "EMP" } }, "required": ["actor_category"] }, "then": { "properties": { "actor_metadata": { "$ref": "#/definitions/EmpSchema" } } } }, { "if": { "properties": { "actor_category": { "const": "MANAGER" } }, "required": ["actor_category"] }, "then": { "properties": { "actor_metadata": { "$ref": "#/definitions/ManagerSchema" } } } } ] }
验证效果
用你提供的问题Payload测试时,现在会正确报错:
actor_category为MANAGER,但actor_metadata使用了EmpSchema的结构,不符合ManagerSchema要求(缺少必填的manager_uuid和manager_dept,且存在不允许的额外属性emp_uuid)
内容的提问来源于stack exchange,提问作者V1666
相关产品推荐
相关产品推荐

