python-jsonschema / python-jsonschema/jsonschema
Question about validators across $refs
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5k
- Forks
- 671
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 10
Description
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)...
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reported outer.json, nested.json, and script, then run the comparison against jsonschema 4.9.1 and 4.10.0. Trace how the custom Draft4 validator is selected across the $ref and document whether the previous default-filling behavior can be preserved without removing $schema.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100