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

Declare keyword use with $schema #918

Open
jdesrosiers opened this issue May 11, 2020 · 4 comments
Open

Declare keyword use with $schema #918

jdesrosiers opened this issue May 11, 2020 · 4 comments
Labels

Comments

@jdesrosiers
Copy link
Member

This is a proposal based on $meta from Hyperjump Validation. $meta is based on the idea of having a separate meta-schema per keyword rather than one meta-schema that covers everything. This is supposed to be a minimal change, but I couldn't come up with something minimal that achieves the same things as $meta. However, I did come up with something that is backwards compatible.

The $schema keyword is used to declare what keywords are allowed to be used in the schema and to tell the validator what keywords need to be supported to validate the schema. Declarations are done by mapping keyword-names to keyword-ids (similar to @context in JSON-LD). This doesn't hurt extensibility because it's so easy to declare your custom keywords.

{
  "$schema": {
    "properties": "https://json-schema.org/draft/future/vocab/applicator/properties",
    "items": "https://json-schema.org/draft/future/vocab/applicator/items",
    "minimum": "https://json-schema.org/draft/future/vocab/validation/minimum",
    "maximum": "https://json-schema.org/draft/future/vocab/validation/maximum",
    ...
  },
  ...
}

Keyword-ids refer to a meta-schema that defines the value for that keyword only.

{
  "$id": "https://json-schema.org/draft/future/vocab/validation/minimum",
  "$schema": "https://json-schema.org/draft/future/schema",
  "type": "number"
}

$schema also allows an array allowing for grouping and composing keywords into vocabularies.

{
  "$schema": [
    {
      "properties": "https://json-schema.org/draft/future/vocab/applicator/properties",
      "items": "https://json-schema.org/draft/future/vocab/applicator/items",
      ...
    },
    {
      "minimum": "https://json-schema.org/draft/future/vocab/validation/minimum",
      "maximum": "https://json-schema.org/draft/future/vocab/validation/maximum",
      ...
    }
  ],
  ...
}

Each item in the array can also be a reference to a keyword declaration to make them easier to reuse and combine.

{
  "$schema": [
    "https://json-schema.org/draft/future/vocab/core",
    "https://json-schema.org/draft/future/vocab/applicator",
    "https://json-schema.org/draft/future/vocab/validation",
    "https://json-schema.org/draft/future/vocab/meta-data",
    "https://json-schema.org/draft/future/vocab/content",
    { "format": "https://json-schema.org/draft/future/schema/format" }
  ],
  ...
}

$schema can also be a reference to a keyword declaration or an array of keyword declarations giving us backwards compatibility with what everyone is used to.

{
  "$schema": "https://json-schema.org/draft/future/schema",
  ...
}

Since there's no such thing as a vocabulary meta-schema, we have nothing to point to when making recursive references. Therefore we need something to flag that the intended value is a schema. There are a few ways to do this. One option is to add a new type called "schema".

{
  "$id": "https://json-schema.org/draft/future/vocab/applicator/properties",
  "$schema": "https://json-schema.org/draft/future/schema",
  "type": "object",
  "patternProperties": {
    "": { "type": "schema" }
  }
}

With this proposal, $vocabulary, $recursiveAnchor, or$recursiveRef are no longer necessary which eliminates some of the most difficult things in the spec to understand and to implement.

A couple of features in draft 2019-09 are lost with this proposal. You can't have an optional vocabulary and there is no separation between semantics and syntax. The latter would be a shame to loose, but optional vocabularies would not be necessary. For example, there would be two separate keyword definition for format: one that's just meta-data and the one that make assertions. Schema authors just need to declare which behavior they want.

@handrews
Copy link
Contributor

Just to note (I have barely skimmed this issue at all) I summarized my prior thought on how to describe keyword behaviors at #911 (comment).

@karenetheridge
Copy link
Member

karenetheridge commented May 12, 2020

If the values under $schema were objects subschemas instead of URL strings, then one can either use a $ref to the metaschema for that keyword, or even include a subschema inlined. I could see inlined metaschemas being quite handy for adhoc testing.

@jdesrosiers
Copy link
Member Author

@handrews I know this isn't exactly what you asked for, but it was the best I could come up with. I'm just not sure this approach meshes well with the current approach. Hopefully it at least inspires some ideas. I'll keep thinking of ways to better incorporate it into what we currently have and your vision of where it might go.

@jdesrosiers
Copy link
Member Author

@karenetheridge That occurred to me as well. I like the idea, but decided the trade-offs weren't worth it. Retrieving the meta-schema is a secondary purpose. The main purpose of using URIs is as an identifier for the semantics for the keyword. The URI would be used by implementations to map the plain-name with the keyword implementation.

As long as the meta-schema has an $id, the implementation can use that as the identifier and it should work. I ended up not going down that path because I thought it obscured to primary purpose too much and made the typical case more verbose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants