Skip to content

Declare keyword use with $schema #918

Open
@jdesrosiers

Description

@jdesrosiers

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions