Skip to content

An alternate approach to meta-schemas #911

Open
@jdesrosiers

Description

Since there's been some discussion about $recusriveAnchor/$recursiveRef lately, it might be a good time to share one of the experimental things I've tried out with Hyperjump Validation. It requires a big change to the concept of meta-schemas, but it eliminates the need for dynamic scope keywords and you basically get vocabulary support for free. It's not perfect and the syntax could certainly use some cleanup, but it has some pretty interesting properties.

In Hyperjump Validation, instead of having a meta-schema that describes a schema, it uses a separate meta-schema for each keyword.

Here's how it works... Keywords are identified by URLs. Each keyword the schema can use is declared using the $meta keyword. $meta works in a very similar way to @context in JSON-LD mapping a plain name to a URL.

{
  "$meta": {
    "type": "https://validation.hyperjump.io/common/type",
    "properties": "https://validation.hyperjump.io/common/properties"
  },
  "type": "object",
  "properties": {
    "foo": { "type": "string" }
  }
}

The URL given to a keyword should be dereferenceable to a schema that validates that keyword. Therefore, a validator can determine if a keyword is valid even if it doesn't know how to evaluate the constraint that keyword expresses.

Declaring keywords this way is like in any programming language where you would import a
dependency before you use it. Any keyword that appears in the schema that is not declared in $meta is an error. Many people have wanted to include "additionalProperties": false in the JSON Schema meta-schema. This constraint provides the protection people want from typos in keyword names without constraining extensibility.

Most people wouldn't want to have to declare every keyword they use this way, so most schemas will likely choose to link to a common $meta that declares all the keywords they use. This list of keywords is effectively a vocabulary. This example uses the standard Hyperjump Validation vocabulary.

{
  "$meta": { "$href": "https://validation.hyperjump.io/common" },
  "type": "object",
  "properties": {
    "foo": { "type": "string" }
  }
}

A vocabulary can be constructed by creating a new $meta document that declares all the keywords for the vocabulary. This could include new keywords mixed with standard keywords or keywords from other vocabularies. When constructing a vocabulary, you can change the name of keywords (like definitions to $defs) just by changing the name of the keyword in the $meta document. Another reason to change the name of something might be when combining two vocabularies that each have a keyword with the same name.

That's all great, but we still need something like the old meta-schema so keyword meta-schemas that include schemas (like properties) can declare that something is a schema. To solve this problem, I created a new keyword called validation (or schema in JSON Schema terms) that is a flag that indicates that the value should be a schema. It doesn't matter what vocabulary of the schema is. The schema will declare it's own vocabulary. This keyword only indicates that it's a schema of some kind.

{
  $meta: { $href: "https://validation.hyperjump.io/common" },
  validation: true
}

I don't imagine that anyone wants to make a change of this magnitude to JSON Schema, but hopefully it inspires people to look at the problem from a different angle and maybe come up with some new ideas that could be applied in a way that wouldn't completely change the way meta-schemas work.

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions