[Python] Can't figure out why json-schema validation not working with recursive defs

Discussão em 'Python' iniciado por Stack, Fevereiro 25, 2025.

  1. Stack

    Stack Membro Participativo

    I've simplified this to make it easier to convey, but I have a yaml I parse using PyYaml and then I want to validate it against a json-schema. I'm struggling to figure out why validation is failing against my schema when I go more than one level deep. I'm using validate from jsonschema package

    Sample YAML:

    TOP_LEVEL_KEY:
    first_level:
    can_be_any_value:
    some_setting: value
    second_level:
    any_value:
    some_setting: value2

    SOME_OTHER_TOP_LEVEL:
    ....


    first_level and second_level are predefined to some Enum list. There can be indeterminate number of levels.

    Schema:

    yaml_schema = {
    '$defs': {
    'ConfigLevel': {
    'type': 'object',
    'propertyNames': {
    'enum': [
    'first_level',
    'second_level',
    ]
    },
    "additionalProperties": {
    'type': 'object', # the 'can_by_any_value' objects
    "additionalProperties": {
    'type': 'object',
    'properties': {
    'some_setting': {
    'type': 'string'
    },
    },
    "additionalProperties": {
    '$ref': '#/$defs/ConfigLevel'
    }
    }
    }
    }
    },
    'type': 'object',
    'additionalProperties': {
    '$ref': '#/$defs/ConfigLevel'
    }
    }


    Sample as written will fail with:

    jsonschema.exceptions.ValidationError: 'can_by_any_value' is not one of ['first_level', 'second_level']


    But this YAML will validate

    TOP_LEVEL_KEY:
    first_level:
    can_be_any_value:
    some_setting: value
    second_level:
    any_value:
    some_setting: value2



    So the issue is when the recursive definition in the additionalProperties with the #/$defs/ConfigLevel but I've simplified it as far as I can go and am stuck.

    Sample PyTest:

    import pytest
    import yaml
    from jsonschema import validate

    @pytest.fixture(scope="module")
    def yaml_fixture() -> str:
    return """
    TOP_LEVEL:
    first_level:
    can_be_any_value:
    some_setting: value
    second_level:
    can_by_any_value:
    some_setting: value2
    """

    def test_validate_yaml(yaml_fixture):
    validate(yaml.safe_load(yaml_fixture), yaml_schema)

    Continue reading...

Compartilhe esta Página