Skip to Content
@jetio/validator docs are live πŸŽ‰
Meta-Schema SystemThe Priority System

The Three-Tier Priority System

@jetio/validator uses a three-tier priority system to determine which meta-schema to use when validating schemas. This provides flexibility while maintaining sensible defaults.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ PRIORITY 1 (HIGHEST) β”‚ β”‚ Method-Level Override β”‚ β”‚ validateSchema(schema, { metaSchema }) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ (if not specified) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ PRIORITY 2 (MEDIUM) β”‚ β”‚ Schema's $schema Keyword β”‚ β”‚ { $schema: "draft-07" } β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ (if not specified) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ PRIORITY 3 (LOWEST) β”‚ β”‚ Instance Default β”‚ β”‚ new JetValidator({ metaSchema: "..." }) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Priority 1: Method-Level Override

Explicitly specify the meta-schema when calling a validation method. Useful for testing cross-draft compatibility, debugging, or temporarily overriding a schema’s declared version.

const schema = { $schema: "https://json-schema.org/draft-07/schema", // schema says Draft-07 type: "string", }; // Validate against Draft 2020-12 instead const isValid = jetValidator.validateSchema(schema, { metaSchema: "draft/2020-12", // Priority 1 overrides Priority 2 });

Testing a schema across every draft:

const drafts = ["draft-06", "draft-07", "draft/2019-09", "draft/2020-12"]; drafts.forEach((draft) => { const isValid = jetValidator.validateSchema(mySchema, { metaSchema: draft }); console.log(`${draft}: ${isValid ? "βœ“ Compatible" : "βœ— Incompatible"}`); });

Priority 2: The Schema’s $schema Keyword

Auto-detect the meta-schema from the schema’s $schema property. This is the normal path for self-documenting schemas.

const draft07Schema = { $schema: "https://json-schema.org/draft-07/schema", // auto-detected type: "string", }; const draft2020Schema = { $schema: "https://json-schema.org/draft/2020-12/schema", // auto-detected type: "string", }; jetValidator.validateSchema(draft07Schema); // uses Draft-07 jetValidator.validateSchema(draft2020Schema); // uses Draft 2020-12

Different drafts can coexist in the same application β€” each schema validates against its own declared version:

const legacyUserSchema = { $schema: "https://json-schema.org/draft-06/schema", type: "object", properties: { name: { type: "string" } }, }; const modernUserSchema = { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { name: { type: "string" } }, unevaluatedProperties: false, // 2020-12 keyword }; jetValidator.validateSchema(legacyUserSchema); // Draft-06 jetValidator.validateSchema(modernUserSchema); // 2020-12

Priority 3: Instance Default

Fallback to the default meta-schema from the constructor. Used for schemas without a $schema keyword, or to enforce a project-wide standard.

const jetValidator = new JetValidator({ metaSchema: "draft-07", // instance default }); loadDraft07(jetValidator); const schema = { type: "string", // no $schema keyword minLength: 5, }; jetValidator.validateSchema(schema); // falls back to Draft-07

Separate instances can hold different defaults β€” one for legacy schemas, one for modern:

const legacyValidator = new JetValidator({ metaSchema: "draft-06" }); loadDraft06(legacyValidator); const modernValidator = new JetValidator({ metaSchema: "draft/2020-12" }); loadDraft202012(modernValidator); legacyValidator.validateSchema(oldSchema); modernValidator.validateSchema(newSchema);

All Three Together

const jetValidator = new JetValidator({ metaSchema: "draft-06", // PRIORITY 3: instance default }); loadAllMetaSchemas(jetValidator); const noSchemaKeyword = { type: "string" }; const draft07Schema = { $schema: "https://json-schema.org/draft-07/schema", // PRIORITY 2 type: "string", }; // No $schema, no override β†’ Priority 3 (draft-06) jetValidator.validateSchema(noSchemaKeyword); // Has $schema, no override β†’ Priority 2 (draft-07) jetValidator.validateSchema(draft07Schema); // Has $schema, with override β†’ Priority 1 wins (draft-06) jetValidator.validateSchema(draft07Schema, { metaSchema: "draft-06", });
Schema $schemaMethod OverrideResult
Not specifiedNot specifiedInstance default
draft-07Not specifieddraft-07 (from schema)
draft-07draft/2020-12draft/2020-12 (override wins)
Not specifieddraft/2020-12draft/2020-12 (override wins)
Last updated on