Description
NOTE: It is 2020. The world has gone to shit, and I'm barely functioning as a human being. But we have a draft to get out and a vague deadline in the form of OAS 3.1. So I'm trying to get this done. HOWEVER I do not have the capacity to debate things in detail. The only things I'm looking for here are:
- Will it work?
- Will it make our lives difficult in a significant way in the future?
If you think you have a substantially better idea, please file it as its own issue and if it is better we will do that. Feel free to cut-and-paste this issue and just change whatever you want to change if it's not completely different.
I am specifically not up for a debate on naming. If a group of people want to go off on slack and reach a consensus that includes at minimum @Relequestual and @gregsdennis on a single proposal of alternative names and bring that back, we'll switch to those. Just don't debate it here.
I am also not interested in what else we could do with a vocabulary file. I have a much more complex idea in my head that would even allow a generic implementation to automatically implement certain classes of keyword straight from the file. But now is not the time for that.
And I am very much not at all interested in revisiting the question of per-vocabulary meta-schemas. I understand that there are redundancies. I understand that not everyone "gets" why I set them up that way. But that discussion is out of scope for this issue, and really for this whole draft.
Yes, I'm being unreasonably dictatorial. None of us are getting what we want this year, are we?
This is an alternative to #995 about a plugin architecture appendix. This approach would support the plugin architecture sketched out there but is more precise.
The format (as I have long said would be the case) is not a schema. There are two top-level keywords:
vocabulary
: this MUST match the URI used in the meta-schema's$vocabulary
keywordkeywords
: the object of keywords defined by this vocabulary.
Within the keywords
object, for each schema keyword there is an object with the following vocabulary file keywords:
inPlaceApplicator
: iftrue
, this keyword is an in-place applicator, and MUST run before any other keyword that depends on annotations collected through adjacent in-place applicators defaults tofalse
dependsOn
: list of annotation names (which are also keyword names) on which this keyword depends; there is no way to distinguish which vocabulary provides the annotation, and as always (yes this is in the spec) combining vocabularies with conflicting semantics produces undefined behavior so just don't defaults to an empty list[]
throughInPlaceApplicators
: iftrue
, the annotations independsOn
need to be examined both as adjacent keywords, and as annotation propagating up through adjacent in-place applicators; iffalse
only adjacent keywords noted independsOn
are to be considered. defaults tofalse
dependsOnValidity
: object of keywords (although really it should only be one but that's should and not SHOULD) that MUST be present and MUST produce the given boolean value assertion result in order for this keyword to be processed
All the usual stuff about $vocabulary
key names / vocabulary
values being URIs and not URLs etc. etc. is the same as for all of the other stuff like this. Furthermore, implementations are welcome to hardcode behavior for well-known vocabularies (e.g. the ones in our spec documents).
This is intended to manage keyword-level dependencies. I am NOT OPEN to vocabulary-level dependencies. Vocabularies are semantic units of convenience that facilitate a plugin architecture. Vocabularies are "aware" of keywords, keywords are not aware of vocabularies. Because reasons.
Since we're documenting dependencies, I wanted to handle if
/then
/else
, and realized I want annotation dependencies and validation dependencies to be handled separately. There's no concept of validation results interacting in a special way with in-place applicators, they just work at the immediately adjacent level. You could in theory depend on both validity and annotations but I wouldn't.
I am open to ONE naming question and only this one: if folks would rather put a $
in front of all of the vocabulary file keywords I'd be OK with that. But this format is not intended to be extensible so idk it just seemed simpler to not bother.
I'm not 100% sure I got all of the keywords here but you get the idea and it shows the dependency stuff.
{
"vocabulary": "https://json-schema.org/2019-09/vocab/core",
"keywords": {
"$schema": {},
"$vocabulary": {},
"$id": {},
"$anchor": {},
"$ref": {
"inPlaceApplicator": true
},
"$dynamicAnchor": {},
"$dynamicRef": {
"inPlaceApplicator": true
},
"$defs": {},
"$comment": {}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/applicator",
"keywords": {
"allOf": {
"inPlaceApplicator": true
},
"anyOf": {
"inPlaceApplicator": true
},
"oneOf": {
"inPlaceApplicator": true
},
"not": {
"inPlaceApplicator": true
},
"if": {
"inPlaceApplicator": true
},
"then": {
"inPlaceApplicator": true,
"dependsOnValidity": {"if": true}
},
"else": {
"inPlaceApplicator": true,
"dependsOnValidity": {"if": false}
},
"dependentSchemas": {
"inPlaceApplicator": true
},
"prefixItems": {},
"items": {
"dependsOn": ["prefixItems"],
"throughInPlaceApplicators": false
},
"contains": {},
"properties": {},
"patternProperties": {},
"additionalProperties": {
"dependsOn": ["properties", "patternProperties"],
"throughInPlaceApplicators": false
},
"propertyNames": {}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/unevaluated",
"keywords": {
"unevaluatedProperties": {
"dependsOn": ["properties", "patternProperties", "additionalProperties", "unevaluatedProperties"],
"throughInPlaceApplicators": true
},
"unevaluatedItems": {
"dependsOn": ["prefixItems", "items", "contains", "unevaluatedItems"],
"throughInPlaceApplicators": true
}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/validation",
"keywords": {
"type": {},
"enum": {},
"const": {},
"minimum": {},
"maximum": {},
"exclusiveMinimum": {},
"exclusiveMaximum": {},
"multipleOf": {},
"minLength": {},
"maxLength": {},
"pattern": {},
"minItems": {},
"maxItems": {},
"minContains": {
"dependsOn": ["contains"]
},
"maxContains": {
"dependsOn": ["contains"]
},
"required": {},
"dependentRequired": {},
"minProperties": {},
"maxProperties": {}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/meta-data",
"keywords": {
"title": {},
"description": {},
"readOnly": {},
"writeOnly": {},
"deprecated": {},
"examples": {},
"default": {}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/format",
"keywords": {
"format": {}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/content",
"keywords": {
"contentMediaType": {},
"contentEncoding": {},
"contentSchema": {}
}
}
{
"vocabulary": "https://json-schema.org/2019-09/vocab/hyper-schema",
"keywords": {
"base": {},
"links": {}
}
}
Metadata
Metadata
Assignees
Type
Projects
Status