JSON schema validator for JavaScript with comprehensive validation capabilities and support for both synchronous and asynchronous validation modes
Schema compilation, caching, and remote reference resolution capabilities for handling complex schema relationships and dependencies. z-schema provides comprehensive tools for managing schemas with remote references and inter-schema dependencies.
Set and manage remote schema references for resolving $ref properties.
/**
* Register a remote schema reference
* @param uri - URI identifier for the schema
* @param schema - Schema object or JSON string
* @param validationOptions - Optional validation options for this schema
*/
setRemoteReference(
uri: string,
schema: any | string,
validationOptions?: ZSchema.Options
): void;Usage Examples:
const ZSchema = require("z-schema");
const validator = new ZSchema();
// Set remote reference from object
const personSchema = {
type: "object",
properties: {
name: { type: "string" },
age: { type: "number" }
},
required: ["name", "age"]
};
validator.setRemoteReference("http://example.com/person", personSchema);
// Set remote reference from JSON string
const addressSchemaJson = JSON.stringify({
type: "object",
properties: {
street: { type: "string" },
city: { type: "string" },
zipCode: { type: "string", pattern: "^\\d{5}$" }
},
required: ["street", "city"]
});
validator.setRemoteReference("http://example.com/address", addressSchemaJson);
// Use schemas with references
const mainSchema = {
type: "object",
properties: {
person: { $ref: "http://example.com/person" },
address: { $ref: "http://example.com/address" }
}
};
// Set with custom validation options
validator.setRemoteReference(
"http://example.com/strict-schema",
strictSchema,
{ strictMode: true, noEmptyStrings: true }
);
const data = {
person: { name: "John Doe", age: 30 },
address: { street: "123 Main St", city: "Anytown", zipCode: "12345" }
};
const valid = validator.validate(data, mainSchema);Set a global function to read schemas synchronously when references are encountered.
/**
* Set global schema reader function (static method)
* @param schemaReader - Function that reads schemas by URI
*/
static setSchemaReader(schemaReader: (uri: string) => any): void;
/**
* Set schema reader function (instance method)
* @param schemaReader - Function that reads schemas by URI
*/
setSchemaReader(schemaReader: (uri: string) => any): void;
/**
* Get current schema reader function
* @returns Current schema reader function or undefined
*/
getSchemaReader(): ((uri: string) => any) | undefined;Usage Examples:
const fs = require("fs");
const path = require("path");
// Set global schema reader
ZSchema.setSchemaReader(function(uri) {
const filename = path.resolve(__dirname, "schemas", uri + ".json");
try {
return JSON.parse(fs.readFileSync(filename, "utf8"));
} catch (error) {
throw new Error(`Could not read schema: ${uri}`);
}
});
// Now schemas will be automatically loaded when referenced
const schema = {
type: "object",
properties: {
user: { $ref: "user" }, // Will load from schemas/user.json
profile: { $ref: "profile" } // Will load from schemas/profile.json
}
};
const validator = new ZSchema();
const valid = validator.validate(data, schema);
// Instance-specific schema reader
const validator2 = new ZSchema();
validator2.setSchemaReader(function(uri) {
// Custom loading logic for this validator instance
return loadSchemaFromDatabase(uri);
});Get fully resolved schemas with all references expanded.
/**
* Get schema with all references resolved
* @param schema - Schema to resolve
* @returns Resolved schema with expanded references
* @throws Error if resolution fails
*/
getResolvedSchema(schema: any): any;Usage Examples:
const validator = new ZSchema();
// Set up remote references
validator.setRemoteReference("http://example.com/address", {
type: "object",
properties: {
street: { type: "string" },
city: { type: "string" }
}
});
// Schema with references
const schema = {
type: "object",
properties: {
name: { type: "string" },
address: { $ref: "http://example.com/address" }
}
};
try {
const resolvedSchema = validator.getResolvedSchema(schema);
console.log(JSON.stringify(resolvedSchema, null, 2));
/* Output:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
}
}
}
}
*/
} catch (error) {
console.error("Schema resolution failed:", error.message);
}Identify missing remote references that need to be resolved.
/**
* Get array of missing references from validation errors
* @param arr - Optional array of errors to check (defaults to last errors)
* @returns Array of missing reference URIs
*/
getMissingReferences(arr?: any[]): string[];
/**
* Get array of missing remote references (URLs only)
* @returns Array of missing remote reference URLs
*/
getMissingRemoteReferences(): string[];Usage Examples:
const validator = new ZSchema();
const schema = {
type: "object",
properties: {
profile: { $ref: "http://example.com/profile" },
settings: { $ref: "http://example.com/settings" },
localRef: { $ref: "#/definitions/local" }
},
definitions: {
local: { type: "string" }
}
};
const valid = validator.validate({}, schema);
if (!valid) {
// Get all missing references
const missingRefs = validator.getMissingReferences();
console.log("Missing references:", missingRefs);
// Output: ["http://example.com/profile", "http://example.com/settings"]
// Get only remote (URL) references
const missingRemote = validator.getMissingRemoteReferences();
console.log("Missing remote references:", missingRemote);
// Output: ["http://example.com/profile", "http://example.com/settings"]
// Load missing schemas
missingRemote.forEach(url => {
const schema = loadSchemaFromSomewhere(url);
validator.setRemoteReference(url, schema);
});
// Retry validation
const validAfterLoad = validator.validate({}, schema);
}Example implementation of automatic remote schema loading.
// Example helper function for automatic schema loading
function validateWithAutomaticLoading(validator, data, schema, callback) {
function attemptValidation() {
const valid = validator.validate(data, schema);
const missingRefs = validator.getMissingRemoteReferences();
if (missingRefs.length > 0) {
let loaded = 0;
const errors = [];
missingRefs.forEach(url => {
// Load remote schema (example using fetch or http)
loadRemoteSchema(url)
.then(remoteSchema => {
validator.setRemoteReference(url, remoteSchema);
loaded++;
if (loaded === missingRefs.length) {
if (errors.length === 0) {
attemptValidation(); // Retry
} else {
callback(errors[0], false);
}
}
})
.catch(error => {
errors.push(error);
loaded++;
if (loaded === missingRefs.length) {
callback(errors[0], false);
}
});
});
} else {
callback(null, valid);
}
}
attemptValidation();
}Usage Examples:
const https = require("https");
function loadRemoteSchema(url) {
return new Promise((resolve, reject) => {
https.get(url, (response) => {
let data = "";
response.on("data", chunk => data += chunk);
response.on("end", () => {
try {
resolve(JSON.parse(data));
} catch (error) {
reject(error);
}
});
}).on("error", reject);
});
}
const validator = new ZSchema();
const schema = {
$ref: "https://json-schema.org/draft-04/schema#"
};
validateWithAutomaticLoading(validator, {type: "string"}, schema, (error, valid) => {
if (error) {
console.error("Loading failed:", error);
} else if (valid) {
console.log("Validation passed");
} else {
console.log("Validation failed:", validator.getLastErrors());
}
});interface ReferenceOptions {
/** Don't fail on unresolvable remote references (default: false) */
ignoreUnresolvableReferences?: boolean;
}Usage Examples:
// Ignore unresolvable references (for testing)
const lenientValidator = new ZSchema({
ignoreUnresolvableReferences: true
});
const schema = {
type: "object",
properties: {
data: { $ref: "http://unreachable.example.com/schema" }
}
};
// This will not fail even though the reference cannot be resolved
const valid = lenientValidator.validate({ data: "test" }, schema);Understanding the internal schema compilation process for advanced usage.
/**
* Compile schema without meta-schema validation
* @param schema - Schema to compile
* @returns boolean indicating compilation success
*/
compileSchema(schema: any): boolean;Usage Examples:
const validator = new ZSchema();
// Compile schema array with inter-references
const schemas = [
{
id: "base",
type: "object",
properties: {
id: { type: "number" }
}
},
{
id: "extended",
allOf: [
{ $ref: "base" },
{
properties: {
name: { type: "string" }
}
}
]
}
];
// Compile all schemas
const compiled = validator.compileSchema(schemas);
if (compiled) {
// Use compiled schema for validation
const valid = validator.validate(
{ id: 1, name: "test" },
schemas.find(s => s.id === "extended")
);
}Schema management operations can fail in various ways. Handle errors appropriately.
interface SchemaManagementErrors {
"UNRESOLVABLE_REFERENCE": "Reference could not be resolved: {0}";
"SCHEMA_NOT_REACHABLE": "Validator was not able to read schema with uri: {0}";
"REF_UNRESOLVED": "Reference has not been resolved during compilation: {0}";
"REMOTE_NOT_VALID": "Remote reference didn't compile successfully: {0}";
}Usage Examples:
const validator = new ZSchema();
try {
const resolvedSchema = validator.getResolvedSchema(schemaWithBadRefs);
} catch (error) {
if (error.name === "z-schema validation error") {
error.details.forEach(detail => {
switch (detail.code) {
case "UNRESOLVABLE_REFERENCE":
console.log(`Cannot resolve reference: ${detail.params[0]}`);
break;
case "SCHEMA_NOT_REACHABLE":
console.log(`Schema not reachable: ${detail.params[0]}`);
break;
default:
console.log(`Schema error: ${detail.message}`);
}
});
}
}Install with Tessl CLI
npx tessl i tessl/npm-z-schema