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

Allow selecting schema from URI #1052

Closed
plondino opened this issue Mar 7, 2023 · 7 comments
Closed

Allow selecting schema from URI #1052

plondino opened this issue Mar 7, 2023 · 7 comments

Comments

@plondino
Copy link

plondino commented Mar 7, 2023

Not sure if this is related to #451, but it would be convenient to access the map of schema URIs to validators (e.g. https://json-schema.org/draft/2020-12/schema -> Draft2012). It looks like this used to be exposed via meta_schemas in validators.py but was deprecated - getting a validator for the schema is useful but sometimes you want to override that and it would be helpful to do that with a string or enum value.

@Julian
Copy link
Member

Julian commented Mar 9, 2023

Hi -- thanks. Can you elaborate a bit more on what you mean by:

getting a validator for the schema is useful but sometimes you want to override that

Override what specifically? Or, what would you do with this mapping? You can create such a mapping yourself via e.g.

{Validator.META_SCHEMA["$id"]: Validator for Validator in [jsonschema.validators.Draft202012Validator, jsonschema.validators.Draft201909Validator, jsonschema.validators.Draft7Validator, jsonschema.validators.Draft6Validator, jsonschema.validators.Draft4Validator]}

though yeah would still love to hear what you'd use it for.

@plondino
Copy link
Author

plondino commented Mar 10, 2023

Thanks for the quick reply. I'm just looking to get a validator by the id string, essentially overriding the default validator specified in the $id field (without modifying the document).

I could construct the dictionary as above, but that means importing and rebuilding the list of validators myself. I could also directly use the private _META_SCHEMAS or its deprecated access via the meta_schemas attr access, but it seems like a "nice to have" as a library function - especially since it's already present, just not exposed.

@Julian
Copy link
Member

Julian commented Mar 10, 2023

essentially overriding the default validator specified in the $id field (without modifying the document).

I'm afraid I still don't follow this -- do you mean the $schema property perhaps rather than $id? And you're trying to change the behavior of some existing drafts? If so I'm also still not 100% sure why you'd need a dictionary to do so, don't you know which draft you're trying to override?

But essentially this is unlikely to come back -- it's not encouraged to override the builtin versions, it's instead a way better idea to create your own dialect with its own $id and to leave the default drafts alone -- eventually when this attribute is removed entirely it will be replaced with something that doesn't involve global state (a global list of validators).

@plondino
Copy link
Author

plondino commented Mar 11, 2023

Sorry, yes I did mean $schema, not $id.

By "override" I mean which validator to use, not anything specific about the validator itself. It's just a tiny bit of syntactic sugar to be able to take the draft specification URI and retrieve the appropriate validator, using the same code that validator_for is already using. Here's an example of what I'm doing now:

def get_validator_from_path(path: pathlib.Path, draft_uri: str = None) -> Validator:    
    with open(path) as f:
        schema = json.load(f)
    if draft_uri:
        return jsonschema.validators._META_SCHEMAS.get(draft_uri)(
            schema, format_checker=jsonschema.FormatChecker())
    return jsonschema.validators.validator_for(schema)(
        schema, format_checker=jsonschema.FormatChecker())

By default, use the schema in the $schema field, but allow the calling code to validate against a different draft. It's just a way to get the validator from some kind of label.

@Julian
Copy link
Member

Julian commented Mar 13, 2023

That looks more or less like why validator_for takes a default argument -- it takes a Validator type, so if you change your function to take a Validator rather than a draft_uri you should just be able to use that directly essentially.

@plondino
Copy link
Author

plondino commented Mar 14, 2023

Sure, but I have to use the class itself, not a lookup based on a string value, which is easier for client code. Again, it's just a minor convenience function to have a way to use the _META_SCHEMAS lookup to get the validator type - if you don't think it's generally useful or a good idea it's not that hard for me to create the map myself.

Overall I really like the library and appreciate the work that has gone into it.

@Julian
Copy link
Member

Julian commented Mar 15, 2023

Thanks for the kind words, definitely appreciated.

I think for now I'd like to err on the side of not adding more here -- it's possible down the line once some of the global state has disappeared (i.e. after some of the deprecated things are removed) that something like this could be in the cards, but for now I don't want to commit to more global state until we have some notion of a dialect registry.

FWIW in case I didn't mention it before, yet another way if you really have a string dialect URI is to simply use validator_for({"$schema": draft_uri}) -- if/when we did have such a function, I think the API would be similar to that anyhow (i.e. a function call, not a dictionary you index into), so really the difference here should be simply needing to wrap things in a trivial schema containing just $schema.

Going to close, but certainly appreciate the report (and again the kind words!)

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