jsonschema 校验正则报 ASCII and UNICODE flags are incompatible
jsonschema 4.26.0 的 regex checker 只转换 re.error,冲突标志会泄漏 ValueError。给专用 FormatChecker 补实例级异常契约,保留字符串类型与正则成本边界。
FormatChecker.conforms() 对普通坏正则返回 False,遇到 (?u)(?a) 却把 ValueError: ASCII and UNICODE flags are incompatible 抛到接口外面。使用 jsonschema 4.26.0 时,这与内置 regex checker 声明捕获的异常范围有关。
该 checker 调用 Python 的 re.compile(),只声明将 re.error 转成格式错误。两个分开的、不兼容的 Unicode 与 ASCII 标志组会触发 ValueError,它不是 re.error 的子类,因此绕过了这层转换。不能由“用了 FormatChecker”推断任意正则输入都会变成普通校验失败。
在专用 checker 实例上补齐这条异常分支
对确实以 Python re 为匹配引擎的应用,可为这个校验入口使用独立实例,明确覆盖不兼容标志产生的 ValueError:
import re
from jsonschema import Draft202012Validator, FormatChecker
checker = FormatChecker()
@checker.checks("regex", raises=(re.error, ValueError))
def is_python_regex(value):
if not isinstance(value, str):
return True
re.compile(value)
return True
schema = {"type": "string", "format": "regex"}
validator = Draft202012Validator(schema, format_checker=checker)
这是实例级覆盖,避免修改其他调用方共享的默认格式表。后续应通过这个 validator 的 iter_errors() 等原有入口消费结果;创建了 checker 却没有传入 validator,不会改变实际校验。
非字符串直接返回 True 是格式 checker 的职责边界,字符串类型要求由 schema 中的 type 承担。不要删除 type 后误以为格式校验会替它拒绝数字或对象。
这项覆盖沿用内置 checker 的 Python 正则语法。若数据契约要求另一种正则方言,应使用对应引擎与规则,不能只因为 Python 能编译,就宣布它符合任意 JSON Schema 使用场景。
异常被转换,不代表正则已经安全
当前修改针对冲突标志的 ValueError。深度嵌套和超大重复次数还可能触发其他异常,不应扩大到捕获所有 Exception 再一概返回“格式不合法”,掩盖校验器自身的程序错误。
外部模式应有应用自己的长度、嵌套或功能限制。re.compile() 成功只说明能编译,不保证随后拿它匹配文本时没有高成本回溯;仅捕获这次异常不能解决正则拒绝服务风险。
检查时保留有效模式、未闭合方括号以及两种冲突标志顺序。有效输入仍应通过,无效输入应进入原来的校验错误响应,不能让服务返回成功或空结果。不要为了“验证异常”在生产接口提交超深或超长模式。
未来改用其他正式版本时,核对内置 checker 的实际异常契约,再决定是否撤除实例覆盖。没有明确的已发布修正前,不能只按版本号变大就删除这条输入边界。


