防止 jsonschema 总是向 URI 发出请求

Keep jsonschema from always making requests to URI

背景

我正在尝试使用 jsonchema 验证 JSON 文件。但是,库正在尝试发出 GET 请求,我想避免这种情况。

from jsonschema import validate

point_schema = {
    "$id": "https://example.com/schemas/point",
    "type": "object",
    "properties": {"x": {"type": "number"}, "y": {"type": "number"}},
    "required": ["x", "y"],
}

polygon_schema = {
    "$id": "https://example.com/schemas/polygon",
    "type": "array",
    "items": {"$ref": "https://example.com/schemas/point"},
}

a_polygon = [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}, {'x': 1, 'y': 2}]

validate(instance=a_polygon, schema=polygon_schema)

错误

我正在尝试使用规范中的 $ref 键连接两个模式:

对我来说不幸的是,这意味着库将向指定的 URI 发出 GET 请求并尝试对其进行解码:

Traceback (most recent call last):
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 777, in resolve_from_url
    document = self.resolve_remote(url)
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 860, in resolve_remote
    result = requests.get(uri).json()
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/requests/models.py", line 910, in json
    return complexjson.loads(self.text, **kwargs)
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 932, in validate
    error = exceptions.best_match(validator.iter_errors(instance))
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/exceptions.py", line 367, in best_match
    best = next(errors, None)
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/_validators.py", line 81, in items
    for error in validator.descend(item, items, path=index):
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/_validators.py", line 259, in ref
    scope, resolved = validator.resolver.resolve(ref)
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 766, in resolve
    return url, self._remote_cache(url)
  File "/home/user/anaconda3/envs/myapp-py/lib/python3.7/site-packages/jsonschema/validators.py", line 779, in resolve_from_url
    raise exceptions.RefResolutionError(exc)
jsonschema.exceptions.RefResolutionError: Expecting value: line 1 column 1 (char 0)

我不想要这个,我只想让 polygon 模式引用正上方的 point 模式(为此目的,多边形是点的列表)。

事实上,这些模式在同一个文件中。

问题

我总能做到以下几点:

point_schema = {
    "$id": "https://example.com/schemas/point",
    "type": "object",
    "properties": {"x": {"type": "number"}, "y": {"type": "number"}},
    "required": ["x", "y"],
}

polygon_schema = {
    "$id": "https://example.com/schemas/polygon",
    "type": "array",
    "items": point_schema,
}

这在技术上可行。

然而,我只是构建一个更大的字典,我不会使用它设计的规范。

如何使用规范来解决我的问题?

您必须为实施提供其他架构。

对于此实现,您必须提供 RefResolver to the validate function

您需要提供一个 base_urireferrer(架构),或者一个包含 URI 到架构的字典的 store

此外,您可以使用函数处理协议。

您的 RefResolver 如下所示...

refResolver = jsonschema.RefResolver(referrer=point_schema, base_uri='https://example.com/schemas/point'