Skip to content
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

Inconsistent behavior when setting default #1295

Closed
AAriam opened this issue Aug 21, 2024 · 1 comment
Closed

Inconsistent behavior when setting default #1295

AAriam opened this issue Aug 21, 2024 · 1 comment

Comments

@AAriam
Copy link

AAriam commented Aug 21, 2024

Using the example in the documentation, extend Draft202012Validator to set default values:

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

validator = extend_with_default(jsonschema.Draft202012Validator)

Our data can be either a string, or an object with property x, which itself can be either a string, or an object with property x1. If x is not provided, the default should be an object, and the default of x1 should be True. The function below creates a schema for this scenario; it also takes an optional schema_url, which if provided, is added as $schema to the subschema where the data is an object:

def make_schema(schema_url: str | None = None) -> dict:
    schema = {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "anyOf": [
            {"type": "string"},
            {
                "$schema": schema_url,
                "type": "object",
                "properties":{
                    "x": {
                        "default": {},
                        "anyOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "object",
                                "properties": {
                                    "x1": {
                                        "default": True
                                    }
                                }
                            }
                        ],
                    }
                },
                "required": ["x"]  
            },
        ]
    }
    if not schema_url:
        schema["anyOf"][1].pop("$schema")
    return schema

Now if we create a schema without schema_url, everything works as expected. For example, if we pass an empty dictionary as our data, it successfully validates, x is set to an empty dict, and the default value of x1 is added to it:

data = {}
schema = make_schema()
validator(schema).validate(data)
print(data)

returns

{'x': {'x1': True}}

However, if schema_url is set to https://json-schema.org/draft/2020-12/schema, then we get a ValidationError:

data = {}
schema = make_schema("https://json-schema.org/draft/2020-12/schema")
validator(schema).validate(data)  # raises ValidationError

Interestingly, if schema_url is set to anything else (either other schema specification URLs or even invalid URLs), again everything works as expected. For example all these work:

for schema_url in ("https://json-schema.org/draft-07/schema", "NOT A URL"):
    data = {}
    schema = make_schema(schema_url)
    validator(schema).validate(data)
    print(data)
@Julian
Copy link
Member

Julian commented Aug 22, 2024

This sounds like the (not yet solved) #994 (which will likely be solved only once we have a new validation API) -- have a look there, and if it seems different let me know.

(PRs to improve the example code are also welcome.)

@Julian Julian closed this as not planned Won't fix, can't repro, duplicate, stale Aug 22, 2024
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

2 participants