Skip to content

Disallow unknown keywords in meta-schema #1611

Open
@gregsdennis

Description

@gregsdennis

As a follow-up to #1610, there has been some discussion in Slack around a proposal I made for a way to allow for extensions to the meta-schema while also disallowing unknown keywords with unevaluatedProperties: false.

After iterating on the idea, we landed on this structure for the meta-schema:

{
  "$schema": "https://json-schema.org/1/2025",
  "$id": "https://json-schema.org/1/2025",

  "type": ["object", "boolean"],
  "properties": {
    "$schema": { "type": "string", "format": "iri" },
    "additionalProperties": { "$ref": "#" } // showing for self-reference
    // ...
  },
  "unevaluatedProperties": false,

  "$dynamicRef": "#extension",

  "$defs": {
    "extension": {
      "$dynamicAnchor": "extension"      
    }
  }
}

Then an extension meta-schema would need to look like this:

{
  "$schema": "https://json-schema.org/1/2025",
  "$id": "https://example.com/custom",
  
  "$ref": "https://json-schema.org/1/2025",

  "$defs": {
    "extension": {
      "$dynamicAnchor": "extension",
      "properties": {
        "foo": true
      }
    }
  }
}

Tracing this through:

  1. Start validation with the custom meta-schema, https://example.com/custom. This registers the $dynamicAnchor.
  2. The custom meta-schema references the base meta-schema (ours).
  3. The base meta-schema has a $dynamicRef: #extension that resolves back to the definition in the custom meta-schema, where any additional properties are defined.
  4. Because these extra properties are now defined via the $dynamicRef applicator, unevaluatedProperties can see them and will know to ignore them.
  5. Lastly, applicators can once again be defined using just $ref: # (like draft 7 and earlier) because the reference back to the custom meta-schema is handled by the base meta-schema root.

It does feel a bit awkward to put your extension information in a $defs entry, but then you're also making a custom meta-schema, which isn't something I expect many people will do.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions