
本文解析为何 json schema 验证未按预期报错,并指出核心问题:属性定义缺失 properties 容器、类型关键字误用 str 而非 string,进而给出符合规范的完整修正 schema 与验证示例。
本文解析为何 json schema 验证未按预期报错,并指出核心问题:属性定义缺失 properties 容器、类型关键字误用 str 而非 string,进而给出符合规范的完整修正 schema 与验证示例。
在使用 jsonschema 库进行数据校验时,若验证始终“静默通过”,即使输入明显违反约束(例如将数组赋值给声明为字符串的字段),往往并非库本身失效,而是 Schema 结构存在语义错误——最典型的问题是将对象的子字段直接平铺在 schema 根层级,而未包裹于 properties 键下。
JSON Schema 规范严格区分顶层关键字与子结构关键字。例如,type、required、properties 是顶层对象的有效关键字;但 retMsg 或 result 这类自定义字段名,必须作为 properties 对象的键值对出现,否则会被完全忽略。同样,"type": "str" 是非法的:JSON Schema 标准中字符串类型必须写作 "string"(而非 Python 中的 str)。
以下是原始错误 schema 的关键问题分析:
- ❌ retMsg 和 result 直接作为根级键存在 → 不被识别为待校验属性
- ❌ "type": "str" → 应为 "type": "string"
- ❌ 缺少根级 properties 容器 → 所有字段定义失效
✅ 正确写法必须将所有字段定义收归 properties 下,并使用标准类型名:
from jsonschema import validate, ValidationError
schema = {
"$schema": "https://json-schema.org/draft-04/schema#",
"type": "object",
"required": ["retMsg", "result"],
"properties": { # ← 必须存在!所有字段定义在此内部
"retMsg": {
"type": "string",
"const": "OK"
},
"result": {
"type": "object",
"required": ["orderId", "orderLinkId"],
"properties": { # ← 嵌套对象也需 properties
"orderId": {"type": "string"},
"orderLinkId": {"type": "string"}
}
}
}
}
raw_data = {
"retMsg": "OK",
"result": {
"orderId": [], # ← 违反 string 类型,应触发报错
"orderLinkId": "abcde"
}
}
try:
validate(instance=raw_data, schema=schema)
print("Validation passed — unexpected!")
except ValidationError as e:
print(f"Validation failed as expected:\n{e.message}")
print(f"Failed at: {e.json_path}")运行上述代码将准确抛出异常:
Validation failed as expected: [] is not of type 'string' Failed at: $.result.orderId
? 关键注意事项:
- properties 是 JSON Schema 中定义对象字段的唯一合法容器,不可省略或替换;
- 所有类型名(如 string、integer、boolean、array、object)均为小写字符串,与编程语言无关;
- required 数组仅声明字段存在性,其对应字段的类型/格式等约束仍需在 properties 内完整定义;
- 推荐使用 jsonschema.validators.Draft7Validator 或更高版本(如 Draft202012Validator),并配合 validator.iter_errors() 进行多错误收集,提升调试效率。
遵循以上规范,即可确保 JSON Schema 验证行为可预测、可调试,并真正发挥数据契约(Data Contract)的保障作用。










