JSON Schema验证未触发预期失败的问题及修复方案
JSON Schema验证不生效的问题解决
基础Schema文件:./resources/json-schemas/simple-person.schema
{ "$id": "http://example.com/json-schemas/simple-person.schema", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Simple Person", "type": "object", "people": { "items": { "properties": { "name": { "type": "string", "description": "The person's name." }, "age": { "type": "integer", "description": "The person's age." } }, "required": [ "name", "age" ] } } }
扩展Schema文件:./extended-person.schema
{ "$id": "http://example.com/extended-person.schema", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Extended Person", "type": "object", "allOf": [ { "$ref": "http://example.com/json-schemas/simple-person.schema" }, { "people": { "items": { "properties": { "height": { "type": "number", "description": "The person's height in centimeters." }, "required": [ "height" ] } } } } ] }
待验证数据集:./person-dataset.json
{ "people": [ { "name": "Bob", "age": 25, "new value": "value" } ] }
验证代码
from pathlib import Path import json from referencing import Registry, Resource from referencing.exceptions import NoSuchResource from jsonschema import Draft202012Validator def retrieve_from_filesystem(uri: str): SCHEMAS = Path("./resources/json-schemas/") if uri.startswith("http://example.com/json-schemas/"): path = SCHEMAS / Path(uri.removeprefix("http://example.com/json-schemas/")) else: raise NoSuchResource(ref=uri) contents = json.loads(path.read_text()) return Resource.from_contents(contents) registry = Registry(retrieve=retrieve_from_filesystem) schema = json.load(Path("./extended-person.schema").open()) instance = json.load(Path("./person-dataset.json").open()) validator = Draft202012Validator(schema, registry=registry) validator.validate(instance)
问题描述
预期验证会失败,原因有两点:
- 数据集中未包含
height属性 - 数据集中存在Schema未定义的
new value属性
但实际验证却通过了,需要修改让此类不符合要求的数据集触发验证失败。
解决方案
1. 修复height必填项的位置错误
扩展Schema中,required: ["height"]被错误地放在了properties内部,导致规则不生效。需要将它移到和properties同级的位置:
修改后的扩展Schema第二个allOf节点:
{ "people": { "items": { "properties": { "height": { "type": "number", "description": "The person's height in centimeters." } }, "required": [ "height" ] } } }
2. 添加禁止额外属性的规则
JSON Schema默认允许对象包含未在properties中定义的属性,需要添加additionalProperties: false来禁止这种情况。
修改基础Schema
在people.items中添加该规则:
{ "$id": "http://example.com/json-schemas/simple-person.schema", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Simple Person", "type": "object", "people": { "items": { "properties": { "name": { "type": "string", "description": "The person's name." }, "age": { "type": "integer", "description": "The person's age." } }, "required": [ "name", "age" ], "additionalProperties": false } } }
修改扩展Schema
同样在第二个allOf节点的people.items中添加该规则:
{ "$id": "http://example.com/extended-person.schema", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Extended Person", "type": "object", "allOf": [ { "$ref": "http://example.com/json-schemas/simple-person.schema" }, { "people": { "items": { "properties": { "height": { "type": "number", "description": "The person's height in centimeters." } }, "required": [ "height" ], "additionalProperties": false } } } ] }
修改完成后,重新运行验证代码,会触发两个验证错误:
- 缺少必填属性
height - 存在未定义的额外属性
new value
内容的提问来源于stack exchange,提问作者A Simple Programmer
相关产品推荐
相关产品推荐

