8000 Incorrect validation of valid payload with valid schema · Issue #1362 · python-jsonschema/jsonschema · GitHub
[go: up one dir, main page]

Skip to content

Incorrect validation of valid payload with valid schema #1362

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
DoDoENT opened this issue May 29, 2025 · 2 comments
Open

Incorrect validation of valid payload with valid schema #1362

DoDoENT opened this issue May 29, 2025 · 2 comments

Comments

@DoDoENT
Copy link
DoDoENT commented May 29, 2025

I have a schema that heavily utilises $dynamicRef to inject parts of schema from other files.

Namely, here is the base schema:

base.json:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "base.json",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "orderNumber": {
            "type": "integer",
            "minimum": 0
        },
        "downstreamNumber": {
            "$dynamicRef": "#specialDownstreamNumber"
        },
        "schemaName": {
            "$dynamicRef": "#concreteName"
        },
        "schemaVersion": {
            "$dynamicRef": "#concreteVersion"
        },
        "timestamp": {
            "type": "integer"
        },
        "data": {
            "$dynamicRef": "#concreteData"
        }
    },
    "required": [
        "data",
        "orderNumber",
        "schemaName",
        "schemaVersion",
        "downstreamNumber",
        "timestamp"
    ],
    "$defs": {
        "name": {
            "const": "base",
            "$dynamicAnchor": "concreteName"
        },
        "version": {
            "const": "0.0.0",
            "$dynamicAnchor": "concreteVersion"
        },
        "data": {
            "not": true,
            "$dynamicAnchor": "concreteData"
        },
        "downstreamNumber": {
            "type": "integer",
            "minimum": 1,
            "$dynamicAnchor": "specialDownstreamNumber"
        }
    }
}

And here is the specific JSON that fills in the data for the base:

camera.json:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "camera.json",
    "$ref": "base.json",
    "$defs": {
        "name": {
            "const": "camera.info",
            "$dynamicAnchor": "concreteName"
        },
        "version": {
            "const": "1.0.0",
            "$dynamicAnchor": "concreteVersion"
        },
        "data": {
            "$dynamicAnchor": "concreteData",
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "cameraFacing": {
                    "enum": [
                        "Front",
                        "Back"
                    ]
                },
                "cameraFrameSize": {
                    "$ref": "#/$defs/size"
                },
                "roi": {
                    "$ref": "#/$defs/size"
                },
                "viewPortAspectRatio": {
                    "type": "number"
                }
            },
            "required": [
                "cameraFacing",
                "cameraFrameSize",
                "roi",
                "viewPortAspectRatio"
            ]
        },
        "downstreamNumber": {
            "type": "integer",
            "minimum": 0,
            "$dynamicAnchor": "specialDownstreamNumber"
        },
        "size": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "width": {
                    "type": "integer"
                },
                "height": {
                    "type": "integer"
                }
            },
            "required": [
                "width",
                "height"
            ]
        }
    }
}

Here is the JSON that I'm trying to validate:

{
    "orderNumber": 4,
    "downstreamNumber": 1,
    "schemaVersion": "1.0.0",
    "schemaName": "camera.info",
    "timestamp": 1756525700,
    "data": {
        "cameraFacing": "Back",
        "cameraFrameSize": {
            "width": 3841,
            "height": 2161
        },
        "roi": {
            "width": 3840,
            "height": 1858
        },
        "viewPortAspectRatio": 2.066
    }
}

Here is how I'm doing the validation:

import json

from pathlib import Path

from jsonschema.validators import Draft202012Validator
from referencing import Registry, Resource


ROOT = Path(__file__).absolute().parent
SCHEMAS = ROOT / Path("schema")


def validate_file(validator: Draft202012Validator, file: Path):
    with open(file, "rt", encoding="utf-8") as f:
        instance = json.load(f)

    instance = json.loads(file.read_text())

    print(f"Validating {file}...")
    validator.validate(instance)


def retrieve_from_filesystem(uri: str):
    path = SCHEMAS / Path(uri)
    contents = json.loads(path.read_text())
    return Resource.from_contents(contents)


def main():
    registry = Registry(retrieve=retrieve_from_filesystem)

    schema_file = SCHEMAS / Path("camera.json")
    with open(schema_file, "rt", encoding="utf-8") as f:
        schema = json.load(f)

    validator = Draft202012Validator(
        schema,
        registry=registry
    )

    tests_path = ROOT / Path("payload")
    for file in tests_path.iterdir():
        validate_file(validator, file)


if __name__ == "__main__":
    main()

The validation fails with exception:

jsonschema.exceptions._WrappedReferencingError: PointerToNowhere: '/$defs/size' does not exist within {'$schema': 'https://json-schema.org/draft/2020-12/schema', '$id': 'base.json', 'type': 'object', 'additionalProperties': False, 'properties': {'orderNumber': {'type': 'integer', 'minimum': 0}, 'downstreamNumber': {'$dynamicRef': '#specialDownstreamNumber'}, 'schemaName': {'$dynamicRef': '#concreteName'}, 'schemaVersion': {'$dynamicRef': '#concreteVersion'}, 'timestamp': {'type': 'integer'}, 'data': {'$dynamicRef': '#concreteData'}}, 'required': ['data', 'orderNumber', 'schemaName', 'schemaVersion', 'downstreamNumber', 'timestamp'], '$defs': {'name': {'const': 'base', '$dynamicAnchor': 'concreteName'}, 'version': {'const': '0.0.0', '$dynamicAnchor': 'concreteVersion'}, 'data': {'not': True, '$dynamicAnchor': 'concreteData'}, 'downstreamNumber': {'type': 'integer', 'minimum': 1, '$dynamicAnchor': 'specialDownstreamNumber'}}}

Which is incorrect, as camera.json does contain /$defs/size. I've tried validating the payload with a different validator and it validates the payload successfully.

I don't see anything wrong with my schema definitions and boon has no problem validating the payload.

Is this a bug in jsonschema library or did I do something wrong and boon fails to detect it?

@Julian
Copy link
Member
Julian commented May 29, 2025

Hi there! It'd help a bit (and make it more likely I can look at this) if you minimize your example to be the smallest possible schema + instance which exhibits the issue (by removing things irrelevant to the error and doing things like moving your schema to be inline in the Python file rather than in multiple files).

Anything's possible, though both this library and boon pass all of the test suite so if there's an issue our first step will be to minimize it so we can add a test to the suite.

@DoDoENT
Copy link
Author
DoDoENT commented May 29, 2025

Here is the smallest repro I managed to make:

base.json:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "base.json",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "data": {
            "$dynamicRef": "#concreteData"
        }
    },
    "required": [
        "data"
    ],
    "$defs": {
        "data": {
            "not": true,
            "$dynamicAnchor": "concreteData"
        }
    }
}

camera.json:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "camera.json",
    "$ref": "base.json",
    "$defs": {
        "data": {
            "$dynamicAnchor": "concreteData",
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "cameraFrameSize": {
                    "$ref": "#/$defs/size"
                }
            },
            "required": [
                "cameraFrameSize"
            ]
        },
        "size": {
            "type": "integer"
        }
    }
}

payload.json:

{
    "data": {
        "cameraFrameSize": 1920
    }
}

The exception is now:

jsonschema.exceptions._WrappedReferencingError: PointerToNowhere: '/$defs/size' does not exist within {'$schema': 'https://json-schema.org/draft/2020-12/schema', '$id': 'base.json', 'type': 'object', 'additionalProperties': False, 'properties': {'data': {'$dynamicRef': '#concreteData'}}, 'required': ['data'], '$defs': {'data': {'not': True, '$dynamicAnchor': 'concreteData'}}}

Boon successfully validates the payload.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0