Python中JSON Schema Draft2019-09验证无详细错误的解决问询
解决jsonschema验证Draft2019-09 Schema时无法获取详细字段错误信息的问题
问题场景
使用Python的jsonschema库验证Draft2019-09版本的JSON Schema时,无法获取到具体的字段级错误信息。例如输入JSON中resending字段应为布尔类型,实际传入字符串"false",但验证结果仅返回数组不匹配contains规则的笼统错误,未提示具体字段的类型问题。
相关代码与数据
Schema:
{ "$schema": "http://json-schema.org/draft/2019-09/schema#", "description": "my schema", "definitions": { "BCCI": { "type": "object", "additionalProperties": false, "properties": { "entityType": { "description": "", "type": "string", "const": "default" }, "function": { "description": "", "codelistName": "ADNFUN", "type": "string", "oneOf": [ {"const": "01"}, {"const": "02"}, {"const": "09"}, {"const": "54"} ] }, "resending": { "description": "", "type": "boolean" }, "afdDefinitionName": { "description": "", "customDescription": "", "type": "string" }, "originalMessageId": { "description": "", "customDescription": "", "type": "string" } }, "required": ["entityType", "function", "afdDefinitionName"] } }, "type": "object", "additionalProperties": false, "properties": { "BCCI": { "type": "array", "uniqueItems": true, "allOf": [ { "minContains": 1, "maxContains": 1, "contains": {"$ref": "#/definitions/BCCI"} } ] } }, "required": ["BCCI"] }
输入JSON:
{ "BCCI": [ { "entityType": "default", "function": "01", "resending": "false", "afdDefinitionName": "example", "originalMessageId": "12345" } ] }
原验证代码:
import json import jsonschema from jsonschema import validate, Draft201909Validator from jsonschema.exceptions import ValidationError json_file = 'path to json instance' json_schema_file = 'path to json schema instance' with open(json_file) as f: document = json.load(f) with open(json_schema_file) as f: schema = json.load(f) try: validate(instance=document, schema=schema) except jsonschema.exceptions.ValidationError as e: print("----------------------------------------------------------") print(e) print("----------------------------------------------------------") print(f"Error message: {e.message}") print(f"Error path: {e.json_path}") print(f"Error path segments: {list(e.path)}") print(f"Failed validator: {e.validator}")
原输出:
---------------------------------------------------------- [{'entityType': 'default', 'function': '01', 'resending': 'false', 'afdDefinitionName': 'example', 'originalMessageId': '12345'}] does not contain items matching the given schema Failed validating 'contains' in schema['properties']['BCCI']['allOf'][0]: {'contains': {'$ref': '#/definitions/BCCI'}, 'maxContains': 1, 'minContains': 1} On instance['BCCI']: [{'afdDefinitionName': 'example', 'entityType': 'default', 'function': '01', 'originalMessageId': '12345', 'resending': 'false'}] ---------------------------------------------------------- Error message: [{'entityType': 'default', 'function': '01', 'resending': 'false', 'afdDefinitionName': 'example', 'originalMessageId': '12345'}] does not contain items matching the given schema Error path: $.BCCI Error path segments: ['BCCI'] Failed validator: contains
原因分析
默认的validate函数仅抛出顶层验证错误,当数组的contains规则验证失败时,不会递归暴露子schema(即#/definitions/BCCI)内部的字段级错误。需要使用对应Draft版本的Validator类,并通过其iter_errors方法遍历所有层级的验证错误。
解决方案
替换原有的validate异常捕获逻辑,使用Draft201909Validator的iter_errors方法获取所有验证错误,包括子字段的具体问题:
修改后的验证代码:
import json import jsonschema from jsonschema import Draft201909Validator json_file = 'path to json instance' json_schema_file = 'path to json schema instance' with open(json_file) as f: document = json.load(f) with open(json_schema_file) as f: schema = json.load(f) # 初始化对应版本的Validator validator = Draft201909Validator(schema) # 获取所有验证错误 errors = list(validator.iter_errors(document)) if errors: print("所有验证错误信息:") print("----------------------------------------------------------") for idx, error in enumerate(errors, 1): print(f"错误 {idx}:") print(f" 错误信息: {error.message}") print(f" JSON路径: {error.json_path}") print(f" 失败的验证规则: {error.validator}") print(f" 预期值: {error.schema.get(error.validator, '')}") print("----------------------------------------------------------") else: print("JSON验证通过")
修改后的输出:
所有验证错误信息: ---------------------------------------------------------- 错误 1: 错误信息: 'false' is not of type 'boolean' JSON路径: $.BCCI[0].resending 失败的验证规则: type 预期值: boolean ---------------------------------------------------------- 错误 2: 错误信息: [{'entityType': 'default', 'function': '01', 'resending': 'false', 'afdDefinitionName': 'example', 'originalMessageId': '12345'}] does not contain items matching the given schema JSON路径: $.BCCI 失败的验证规则: contains 预期值: {'$ref': '#/definitions/BCCI'} ----------------------------------------------------------
此时可以清晰看到resending字段的类型错误,以及顶层数组的contains验证错误。
内容的提问来源于stack exchange,提问作者MykG
相关产品推荐
相关产品推荐

