DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

jsonschema 的布尔 items 配合 unevaluatedItems 报 len(bool)

jsonschema 4.26.0 的 Draft 2019-09 路径会对布尔 items 求长度。允许任意元素时可改用空对象 schema;拒绝元素的 false 不能同样改写,以免放宽数据契约。

使用 Draft201909Validator 校验下面的 schema,check_schema() 可以通过,真正校验数组时却可能抛出 TypeError: object of type 'bool' has no len():

from jsonschema import Draft201909Validator

schema = {"items": True, "unevaluatedItems": False}
Draft201909Validator.check_schema(schema)
errors = list(Draft201909Validator(schema).iter_errors([1, 2]))

jsonschema 4.26.0 的这条组合存在实现问题。Draft 2019-09 允许布尔 schema,items: true 表示每个元素都满足这一规则;它不是把 True 当成数组长度。

校验器为 unevaluatedItems 收集已处理的元素索引时,只把对象形式的 items 识别为单个 schema,其他值继续按元组校验的 schema 数组计算长度。布尔值因而落到了 len() 上。即使待校验数组为空,也可能在这里失败。

允许任意元素时,可改用空对象 schema

对确实使用 items: true 的这一处规则,可以保留同一草案和外围约束,改成对象形式:

schema = {
    "type": "array",
    "items": {},
    "unevaluatedItems": False,
}
validator = Draft201909Validator(schema)
errors = list(validator.iter_errors([1, 2]))

这段沿用前面的导入。空对象 schema 允许任意元素,避免布尔值进入错误的长度分支;新增的 type 明确要求数组,如原契约允许其他类型,不要无条件加上它。

items: false 则表示不允许任何数组元素,不能同样替换成 {},否则会放宽校验。若必须以对象表达拒绝全部元素的规则,可评估 items: {"not": {}}:空数组仍可通过,非空数组必须失败。它保留允许与拒绝的方向,不保证产生与原布尔 schema 完全相同的错误条数和路径。

复杂 schema 还可能通过 $ref、allOf 等引用到布尔 items。只改最外层一处未必覆盖实际入口,应定位触发索引收集的具体规则,并保留原 schema 及其版本。

不要为了消除异常直接删掉未评估项限制

截至核对,正式 4.26.0 仍包含上述分支,不能仅凭开发修补建议假定已发布修复。也不宜直接切换成 Draft202012Validator:2020-12 的数组关键字与元组校验规则已有变化,草案迁移应作为独立的数据契约调整。

在隔离校验入口保留空数组、非空数组和业务不允许的元素,分别检查接受或拒绝结果。对 items: false 的规避尤其要确认非空数组没有被误放行。通过 iter_errors() 收集应有的验证错误,而不是捕获这条内部 TypeError 后返回“校验成功”。

如果异常来自布尔类型的业务数据、正则 format checker,或另一份 schema 的长度计算,则不属于这条 Draft 2019-09 组合,应沿实际堆栈重新判断。