openapi-schema-validator icon indicating copy to clipboard operation
openapi-schema-validator copied to clipboard

Getting PointerToNowhere when migrating from RefResolver to referencing

Open stefanofusai opened this issue 1 year ago • 1 comments

Dear team, I've been trying my best to migrate my schema validation from RefResolver to the newer referencing library, but with no avail. I would really appreciate some help or tips to point me in the right direction.

What is working for me, with RefResolver, is the following code:

def validate_schema(
    instance: dict[str, Any],
    schema: dict[str, Any],
    *,
    path: str,
    method: str,
    response: str,
    content: str = "application/json",
) -> None:
    try:
        _methods = schema["paths"][path]

    except KeyError:  # pragma: no cover (should never happen)
        msg = f"Path {path} not found in schema"
        raise ValueError(msg) from None

    try:
        _responses = _methods[method]

    except KeyError:  # pragma: no cover (should never happen)
        msg = f"Method {method} not found in schema"
        raise ValueError(msg) from None

    try:
        _content = _responses["responses"][response]["content"]

    except KeyError:  # pragma: no cover (should never happen)
        msg = f"Response {response} not found in schema"
        raise ValueError(msg) from None

    try:
        _schema = _content[content]["schema"]

    except KeyError:  # pragma: no cover (should never happen)
        msg = f"Content {content} not found in schema"
        raise ValueError(msg) from None

    openapi_schema_validator.validate(
        instance,
        _schema,
        cls=OAS30Validator,
        resolver=RefResolver.from_schema(schema),  # TODO: migrate to referencing lib
    )

I then tried to migrate to the referencing lib as mentioned here:

resource = Resource.from_contents(schema, default_specification=DRAFT202012)
registry = Registry().with_resource("", resource)
openapi_schema_validator.validate(instance, _schema, registry=registry)

But with no success, as all I get are errors like: jsonschema.exceptions._WrappedReferencingError: PointerToNowhere: '/components/schemas/Foo' does not exist within {'$ref': '#/components/schemas/Foo'}

What am I missing? Thank you for the help.

stefanofusai avatar Oct 02 '24 16:10 stefanofusai

Instead of passing a registry, you can flatten the schema dict before handing it to the validate function.

To correctly handle $ref pointers directly when parsing your YAML files, you can use a library like PyYAML combined with jsonschema's RefResolver or openapi-spec-validator to properly resolve $ref references. A more elegant solution for loading and resolving references in OpenAPI or YAML schemas is using the yaml loader from jsonschema or openapi-spec-validator libraries.

However, if your project requires loading complex OpenAPI files with nested $ref pointers, the prance library might be the most straightforward choice:

from prance import ResolvingParser
parser = ResolvingParser("openapi.yaml", lazy=True)
parser.parse()
validate_schema(schema=parser.specification, ...)

Gogowitsch avatar Oct 10 '24 13:10 Gogowitsch