Skip to content

Question about validators across $refs #1341

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
kulikjak opened this issue Apr 3, 2025 · 0 comments
Open

Question about validators across $refs #1341

kulikjak opened this issue Apr 3, 2025 · 0 comments

Comments

@kulikjak
Copy link

kulikjak commented Apr 3, 2025

Hi, I have a question regarding the change in 4.10.0 and the default filling custom validator suggested here.

Before this version, I could use this enhanced validator to fill in default values even across "$ref"s to different schema.

But 4.10.0 added support "for referencing schemas with $ref across different versions of the specification", which means that now the validator is determined dynamically based on the "$schema" and the custom one is not used for the referred schema.

Here is an example:

outer:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "properties": {
        "count": {
            "default": 0,
            "type": "integer"
        },
        "nested": {
            "$ref": "file://nested.json"
        }
    }
}

nested:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "properties": {
        "nestedcount": {
            "default": 0,
            "type": "integer"
        },
        "name": {
            "type": "string"
        }
    }
}

script:

import copy
import json
import jsonschema

def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator, properties, instance, schema):
        for property, subschema in properties.items():
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])

        for error in validate_properties(
            validator, properties, instance, schema,
        ):
            yield error

    return jsonschema.validators.extend(
        validator_class, {"properties" : set_defaults},
    )

Draft4ValidatorWithDefaults = extend_with_default(jsonschema.Draft4Validator)


def load_schema(uri):
	with open(uri.removeprefix("file://")) as ifile:
		return json.load(ifile)

schema = load_schema("outer.json")

resolver = jsonschema.RefResolver(
    "outer.json", schema,
    handlers={"file": load_schema})

validator_with_defaults = Draft4ValidatorWithDefaults(schema, resolver=resolver)
validator = jsonschema.Draft4Validator(schema, resolver=resolver)

content = {
	"nested": {"name": "foo"}
}

print(jsonschema.__version__)
validator.validate(content)
print(content)
validator_with_defaults.validate(content)
print(content)

When I run this with jsonschema 4.9.1, I get:

4.9.1
{'nested': {'name': 'foo'}}
{'nested': {'name': 'foo', 'nestedcount': 0}, 'count': 0}

when I use 4.10.0, it looks like this:

4.10.0
{'nested': {'name': 'foo'}}
{'nested': {'name': 'foo'}, 'count': 0}

My question is, is there a way to revert to the previous behavior? I found out that when I delete the "$schema" key from the referred schema, it works as before, but that doesn't seem exactly nice (and I am not sure that won't cause other issues)...

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

1 participant