json-schema-spec
json-schema-spec copied to clipboard
Wild idea for vocabs
I had a weird-but-maybe-good idea about how vocabularies could work.
C# has the using
directive which declares a namespace containing types that are used throughout the file.
Javascript has the import
directive, which kinda does the same thing. The cool thing about imports, though, is you can pull in specific exports from the target and you can rename the exports to something else.
So what if a vocab declaration did the same thing? What if the value inside the $vocabulary
keyword was expanded to support more than a boolean?
My idea was for it to support an object that has two properties:
-
using
would be an array of the keywords from the vocab that could be used in a schema -
remap
would be an object of strings mapping vocabulary keywords to new keywords
It could look like this:
{
"$vocabulary": {
// takes only anyOf, allOf, and oneOf, but remaps oneOf to takeOne
"https://json-schema.org/draft/next/vocab/applicator": {
"using": ["anyOf", "allOf"],
"remap": {
"oneOf": "takeOne"
}
},
// takes all keywords as they are
"https://json-schema.org/draft/next/vocab/validation": true,
// takes all keywords, but remaps title to name
"https://json-schema.org/draft/next/vocab/meta-data": {
"remap": {
"title": "name"
}
},
// ...
}
}
(The word "import" has a history with JSON Schema of being the keyword of choice for people trying to recommend a way to support polymorphism. Also OpenAPI 4 is looking to define it. So it's probably best we stay away from that. I've used "using" here, but I'm open to other suggestions.)
If the value is true
, then it takes the vocab as-is. If using
is missing, it takes all of the keywords.
This allows users to take only specific keywords or to remap keywords, which handles "json schema but in spanish" and provides a way to handle keyword name conflicts.
A false
value could still mean that the vocab is optional, but implementations can only refuse to process the schema if it actually uses the keywords from that unknown vocab. Basically, the implementation's saying, "Hey, I don't know this vocab. Hope you don't use keywords from it..." The use case for this would be having a single meta-schema to describe multiple schemas, where only some of those schemas use the optional keywords. (Seems like a stretch use case when you could just have two meta-schemas, one with the vocab and one without it.)
This renders all current usages of $vocabulary
still valid, so it's backward compatible!
This might be something we could consider putting into place until we develop $dialect
or something else that's better.
There are two catches here:
- Renaming keywords like this requires a meta-analysis prior to (or just before but part of) evaluation, which is a behavior that JSON Schema doesn't have yet
- Meta-schema evaluation is going to be difficult. We'd have to require that meta-schema evaluating means reversing the keyword mappings in order to make the property names align with what's in
properties
. This further makes meta-schema evaluation a special task, separate from merely evaluating the schema like an instance.
Also, since the core vocab is implied anyway (it's a current requirement), I'd add a requirement that it can't be listed here to prevent its keywords from being remapped.
(Lastly, to be clear, I'm offering this option knowing full well that it would likely be a pain to implement in my architecture.)