JaySchema
Unmaintained
:warning: This project is no longer maintained. This was one of the first validators to support JSON Schema v4, and to pass all of the tests that were available at that time. But today there are other options that use better parsing and are much faster, such as ajv, is-my-json-valid, and many more. If you’re happy with JaySchema, feel free to continue using it. If you’d like to take ownership of the project, contact me, but you’re probably better off switching to a modern alternative.
About
A JSON Schema validator for Node.js.
- Complete validation coverage of JSON Schema Draft v4.
- Optional dynamic loader for referenced schemas (load schemas from a database or the web)
- Useful error messages.
- NEW: Supports custom validators for the
format
keword.
Install
npm install jayschema
Usage
CLI
If you install the package globally (npm install -g jayschema
), then you can directly invoke it from the command-line:
$ jayschema my-schema.json
Basic usage
var JaySchema = require('jayschema');
var js = new JaySchema();
var instance = 64;
var schema = { "type": "integer", "multipleOf": 8 };
console.log('synchronous result:', js.validate(instance, schema));
js.validate(instance, schema, function(errs) {
if (errs) { console.error(errs); }
else { console.log('async validation OK!'); }
});
Loading schemas from HTTP or from your database
Here the Geographic Coordinate schema is loaded over HTTP. You can also supply your own loader—for example, to load schemas from a database.
var JaySchema = require('jayschema');
var js = new JaySchema(JaySchema.loaders.http);
var instance = { "location": { "latitude": 48.8583, "longitude": 2.2945 } };
var schema = {
"type": "object",
"properties": {
"location": { "$ref": "http://json-schema.org/geo" }
}
};
js.validate(instance, schema, function(errs) {
if (errs) { console.error(errs); }
else { console.log('validation OK!'); }
});
Custom format validators
Create a custom validator for the JSON Schema format
keyword:
var JaySchema = require('jayschema');
var js = new JaySchema();
js.addFormat('phone-us', function(value) {
var PHONE_US_REGEXP = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
if (PHONE_US_REGEXP.test(value)) { return null; }
return 'must be a US phone number';
});
var instance = '212-555-';
var schema = { "type": "string", "format": "phone-us" };
console.log(js.validate(instance, schema));
Why JSON Schema?
- Validate JSON server-side:
- For your JSON-based API
- For data that you want to store in a NoSQL database
- No ORM required. Change databases or store data in multiple databases using the same schemas. For example, session data in Redis, permanent data in MongoDB.
- JSON Schema has a really nice declarative syntax. See the official examples.
API
JaySchema([loader])
(Constructor) The optional loader will be called each time an external $ref
is encountered. It should load the referenced schema and return it.
If you don’t reference any external schemas, or if you pre-register all the schemas you’re using, you don’t need to provide a loader.
If you provide a loader, you should call the validate() function asynchronously. That’s because loading involves disk or network I/O, and I/O operations in Node are asynchronous.
Sample loader skeleton:
function loader(ref, callback) {
if (errorOccurred) {
callback(err);
} else {
callback(null, schema);
}
}
JaySchema.prototype.validate(instance, schema [, callback])
Validate a JSON object, instance, against the given schema. If you provide a callback, validation will be done asynchronously.
schema can be an actual JSON Schema (a JSON object), or it can be the id
of a previously-registered schema (a string).
Return value
- async: Uses the standard Node callback signature. The first argument will be an array of errors, if any errors occurred, or
undefined
on success. - synchronous: If you don’t provide a callback, an array of errors will be returned. Success is indicated by an empty array.
JaySchema.prototype.register(schema [, id])
Manually register schema. Useful if you have several related schemas you are working with. The optional id can be used to register a schema that doesn’t have an id
property, or which is referenced using a unique id.
Returns: an array of missing schemas. A missing schema is one that was $ref
erenced by the registered schema, but hasn’t been regisetered yet. If no missing schemas were referenced, an empty array is returned.
See Schema loading.
JaySchema.prototype.getMissingSchemas()
Returns an array of missing schemas. A missing schema is one that was $ref
erenced by a register()
ed schema, but the referenced schema has not yet been loaded.
See Schema loading.
JaySchema.prototype.isRegistered(id)
Return boolean indicating whether the specified schema id has previously been registered.
See Schema loading.
JaySchema.prototype.addFormat(formatName, handler)
Add a custom handler for the format
keyword. Whenever a schema uses the format
keyword, with the given formatName
, your handler will be called.
The handler receives the value to be validated, and returns null
if the value is valid, or a string
(description of the error) if the value is not valid.
Loaders
A loader can be passed to the constructor, or you can set the loader
property at any time. You can define your own loader. JaySchema also includes one built-in loader for your convenience:
JaySchema.loaders.http
Loads external $ref
s using HTTP. :warning: Caveat: HTTP is inherently unreliable. For example, the network or site may be down, or the referenced schema may not be available any more. You really shouldn’t use this in production, but it’s great for testing.
Configuration options
maxRecursion
The maximum depth to recurse when retrieving external $ref
schemas using a loader. The default is 5
.
loader
The schema loader to use, if any. (The same schema loader that was passed to the JaySchema
constructor.) You can change or override this at any time.
Schema loading
JaySchema provides several ways to register externally-referenced schemas.
You use the $ref
keyword to pull in an external schema. For example, you might reference a schema that’s available in a local database.
Validation will fail if JaySchema encounters a validation rule that references an external schema, if that schema is not register
ed.
There are several ways to ensure that all referenced schemas are registered:
Using a loader
Pass a loader
callback to the JaySchema
constructor. When an external schema is needed, JaySchema will call your loader. See the constructor documentation, above. Using a loader requires you to validate asynchronously.
By using the getMissingSchemas()
method
This works with synchronous or async code.
- First,
register()
the main schemas you plan to use. - Next, call
getMissingSchemas
, which returns an array of externally-referenced schemas. - Retrieve and
register()
each missing schema. - Repeat from step 2 until there are no more missing schemas.
By using the register()
return value
This works with synchronous or async code.
Each time you call register(schema)
, the return value will be an array of missing external schemas that were referenced. You can use this to register the missing schemas.
In other words: calling register(schemaA);
will (1) register schemaA
and (2) return a list of missing schemas that were referenced by schemaA
.
If, instead, you want the list of all missing schemas referenced by all registrations that have been done so far, use the getMissingSchemas()
method, above.
Format specifiers
For the format
keyword, JaySchema allows you to add custom validation functions (see addFormat
). In addition, the following built-in formats are supported:
date-time
: Must match the date-time
specification given in RFC 3339, Section 5.6. This expects both a date and a time. For date-only validation or time-only validation, JaySchema supports the older draft v3 date
and time
formats.hostname
: Must match the “Preferred name syntax” given in RFC 1034, Section 3.5, with the exception that hostnames are permitted to begin with a digit, as per RFC 1123 Section 2.1.email
: Must match RFC 5322, Section 3.4.1, with the following limitations: quoted-string
s, domain-literal
s, comments, and folding whitespace are not supported; the domain
portion must be a hostname as in the hostname
keyword.ipv4
: Must be a dotted-quad IPv4 address.ipv6
: Must be a valid IPv6 address as per RFC 2373 section 2.2.uri
: As in RFC 3986 Appendix A, including relative URIs (no scheme part, fragment-only), with the exception that well-formedness of internal elements, including percent encoding and authority strings, is not verified.