Skip to content

Question about validators across $refs #1341

@kulikjak

Description

@kulikjak

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)...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions