JSON Schema oneOf校验报错:数据匹配多个子Schema问题排查
问题:JSON Schema oneOf验证失败,提示多个schema匹配
验证DRUGTREATMENT类型数据时触发错误:
should be valid to one and only one of schema, but more than one are valid: {"$ref":"#/$defs/drug-treatment"}{"$ref":"#/$defs/surgery-treatment"}
原Schema定义
{ "$id": "someid", "$schema": "https://json-schema.org/draft/2020-12/schema", "description": "JSON Schema for treatments", "oneOf" : [ { "$ref" : "#/$defs/drug-treatment" }, { "$ref" : "#/$defs/surgery-treatment" } ], "$defs": { "base": { "type": "object", "properties": { "type-tag": { "enum": [ "SURGERY", "DRUGTREATMENT", "RADIOLOGY", "PHYSIOTHERAPY" ] }, "id": { "type": "string", "format": "uuid" }, "patient-id": { "type": "string", "format": "uuid" }, "patient-name": { "type": "string" }, "provider-id": { "type": "string", "format": "uuid" }, "provider-name": { "type": "string" }, "diagnosis": { "type": "string" }, "followup-treatments": { "type" : "array", "items" : { "$ref" : "#" } } }, "required": [ "id", "type-tag", "patient-id", "patient-name", "provider-id", "provider-name", "diagnosis", "followup-treatments" ] }, "drug-treatment": { "allOf": [ { "$ref" : "#/$defs/base" } ], "properties": { "drug": { "type": "string" }, "dosage": { "type": "number" }, "start-date": { "type": "string", "format": "date" }, "end-date": { "type": "string", "format": "date" }, "frequency": "integer" }, "required": [ "drug", "dosage", "start-date", "end-date", "frequency" ], "unevaluatedProperties" : false }, "surgery-treatment": { "allOf": [ { "$ref" : "#/$defs/base" } ], "properties": { "surgery-date": { "type": "string", "format": "date" }, "discharge-instructions": { "type": "string" }, "required": [ "surgery-date", "discharge-instructions" ], "unevaluatedProperties" : false } }, } }
示例验证数据
"treatments": [ { "type-tag": "DRUGTREATMENT", "drug": "fdsds", "dosage": 2.0, "start-date": "2222-02-12", "end-date": "2222-02-12", "frequency": 2, "id": "aa7da984-0252-45b1-b0cd-f1dbe98662e2", "patient-id": "ab62420e-0bd8-4e39-8e0b-36e464b7abb2", "patient-name": "Tom", "provider-id": "154523b2-7598-4ed4-aab1-b2ef1692109c", "provider-name": "gdsfdsd", "diagnosis": "sfdsfds", "followup-treatments": [] }, { "type-tag": "SURGERY", "surgery-date": "2222-02-12", "discharge-instructions": "dsfdsfdsfds", "id": "12d2e565-8966-4029-840b-1959277b37f6", "patient-id": "ab62420e-0bd8-4e39-8e0b-36e464b7abb2", "patient-name": "Tom", "provider-id": "154523b2-7598-4ed4-aab1-b2ef1692109c", "provider-name": "gdsfdsd", "diagnosis": "fdsfds", "followup-treatments": [], } ]
问题根源
- surgery-treatment结构错误:
required和unevaluatedProperties被错误嵌套在properties字段内部,导致这两个约束完全不生效。此时surgery-treatment仅继承base的规则,没有自身的必填字段校验,也不限制额外属性。 - 子Schema无互斥性:DRUGTREATMENT类型的数据既满足drug-treatment的所有规则,又因为surgery-treatment的约束失效,只要符合base规则就会被通过,最终同时匹配两个schema,触发oneOf的“只能匹配一个”校验错误。
修复后的Schema
{ "$id": "someid", "$schema": "https://json-schema.org/draft/2020-12/schema", "description": "JSON Schema for treatments", "oneOf" : [ { "$ref" : "#/$defs/drug-treatment" }, { "$ref" : "#/$defs/surgery-treatment" } ], "$defs": { "base": { "type": "object", "properties": { "type-tag": { "enum": [ "SURGERY", "DRUGTREATMENT", "RADIOLOGY", "PHYSIOTHERAPY" ] }, "id": { "type": "string", "format": "uuid" }, "patient-id": { "type": "string", "format": "uuid" }, "patient-name": { "type": "string" }, "provider-id": { "type": "string", "format": "uuid" }, "provider-name": { "type": "string" }, "diagnosis": { "type": "string" }, "followup-treatments": { "type" : "array", "items" : { "$ref" : "#" } } }, "required": [ "id", "type-tag", "patient-id", "patient-name", "provider-id", "provider-name", "diagnosis", "followup-treatments" ] }, "drug-treatment": { "allOf": [ { "$ref" : "#/$defs/base" } ], "properties": { "drug": { "type": "string" }, "dosage": { "type": "number" }, "start-date": { "type": "string", "format": "date" }, "end-date": { "type": "string", "format": "date" }, "frequency": { "type": "integer" } }, "required": [ "drug", "dosage", "start-date", "end-date", "frequency" ], "unevaluatedProperties" : false }, "surgery-treatment": { "allOf": [ { "$ref" : "#/$defs/base" } ], "properties": { "surgery-date": { "type": "string", "format": "date" }, "discharge-instructions": { "type": "string" } }, "required": [ "surgery-date", "discharge-instructions" ], "unevaluatedProperties" : false } } }
关键修复点
- 将surgery-treatment的
required和unevaluatedProperties从properties内部移到外部,让约束生效 - 修正drug-treatment中
frequency字段的错误写法,从"frequency": "integer"改为"frequency": { "type": "integer" } - 移除Schema末尾多余的逗号,避免JSON解析错误
修复原理
修复后,surgery-treatment会校验surgery-date和discharge-instructions是否存在,DRUGTREATMENT类型的数据因缺少这两个字段,会被surgery-treatment拒绝,最终仅匹配drug-treatment一个schema,满足oneOf的校验要求。同时unevaluatedProperties: false会限制每个子类型只能拥有自身定义的属性,彻底避免跨类型误匹配。
内容的提问来源于stack exchange,提问作者Dilantha
相关产品推荐
相关产品推荐

