Skip to content

Question about validators across $refs #1341

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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