auth0/z-schema

Name: z-schema

Owner: Auth0

Description: JSON Schema validator written in JavaScript for NodeJS and Browsers

Forked from: zaggino/z-schema

Created: 2016-12-30 19:20:39.0

Updated: 2016-12-30 19:20:41.0

Pushed: 2017-01-04 18:56:04.0

Homepage:

Size: 5119

Language: JavaScript

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

npm version bower version build status coverage status

dependencies Status devDependencies Status optionalDependencies Status

z-schema validator

NPM

Topics

Usage

Validator will try to perform sync validation when possible for speed, but supports async callbacks when they are necessary.

Development:

These repository has several submodules and should be cloned as follows:

git clone –recursive https://github.com/zaggino/z-schema.git

CLI:
install --global z-schema
hema --help
hema mySchema.json
hema mySchema.json myJson.json
hema --strictMode mySchema.json myJson.json
NodeJS:
ZSchema = require("z-schema");
options = ... // see below for possible option values
validator = new ZSchema(options);
Sync mode:
valid = validator.validate(json, schema);
his will return a native error object with name and message
error = validator.getLastError();
his will return an array of validation errors encountered
errors = validator.getLastErrors();

Async mode:
dator.validate(json, schema, function (err, valid) {
...

Browser:
ipt type="text/javascript" src="../dist/ZSchema-browser-min.js"></script>
ipt type="text/javascript">
var validator = new ZSchema();
var valid = validator.validate("string", { "type": "string" });
console.log(valid);
ript>
Remote references and schemas:

In case you have some remote references in your schemas, you have to download those schemas before using validator. Otherwise you'll get `UNRESOLVABLE_REFERENCE` error when trying to compile a schema.

validator = new ZSchema();
json = {};
schema = { "$ref": "http://json-schema.org/draft-04/schema#" };

valid = validator.validate(json, schema);
errors = validator.getLastErrors();
alid === false
rrors.length === 1
rrors[0].code === "UNRESOLVABLE_REFERENCE"

requiredUrl = "http://json-schema.org/draft-04/schema";
est(requiredUrl, function (error, response, body) {

validator.setRemoteReference(requiredUrl, JSON.parse(body));

var valid = validator.validate(json, schema);
var errors = validator.getLastErrors();
// valid === true
// errors === undefined


If you're able to load schemas synchronously, you can use ZSchema.setSchemaReader feature:

ema.setSchemaReader(function (uri) {
var someFilename = path.resolve(__dirname, "..", "schemas", uri + ".json");
return JSON.parse(fs.readFileSync(someFilename, "utf8"));

Features

Validate against subschema

In case you don't want to split your schema into multiple schemas using reference for any reason, you can use option schemaPath when validating:

valid = validator.validate(cars, schema, { schemaPath: "definitions.car.definitions.cars" });

See more details in the test.

Compile arrays of schemas and use references between them

You can use validator to compile an array of schemas that have references between them and then validate against one of those schemas:

schemas = [
{
    id: "personDetails",
    type: "object",
    properties: {
        firstName: { type: "string" },
        lastName: { type: "string" }
    },
    required: ["firstName", "lastName"]
},
{
    id: "addressDetails",
    type: "object",
    properties: {
        street: { type: "string" },
        city: { type: "string" }
    },
    required: ["street", "city"]
},
{
    id: "personWithAddress",
    allOf: [
        { $ref: "personDetails" },
        { $ref: "addressDetails" }
    ]
}


data = {
firstName: "Martin",
lastName: "Zagora",
street: "George St",
city: "Sydney"


validator = new ZSchema();

ompile & validate schemas first, z-schema will automatically handle array
allSchemasValid = validator.validateSchema(schemas);
llSchemasValid === true

ow validate our data against the last schema
valid = validator.validate(data, schemas[2]);
alid === true
Register a custom format

You can register any format of your own. Your sync validator function should always respond with a boolean:

ema.registerFormat("xstring", function (str) {
return str === "xxx";

Async format validators are also supported, they should accept two arguments, value and a callback to which they need to respond:

ema.registerFormat("xstring", function (str, callback) {
setTimeout(function () {
    callback(str === "xxx");
}, 1);

Helper method to check the formats that have been registered
registeredFormats = ZSchema.getRegisteredFormats();
gisteredFormats will now contain an array of all formats that have been registered with z-schema
Automatic downloading of remote schemas

Automatic downloading of remote schemas was removed from version `3.x` but is still possible with a bit of extra code, see this test for more information on this.

Prefill default values to object using format

Using format, you can pre-fill values of your choosing into the objects like this:

ema.registerFormat("fillHello", function (obj) {
obj.hello = "world";
return true;


data = {};

schema = {
"type": "object",
"format": "fillHello"


dator.validate(data, schema);
ata.hello === "world"

Options

asyncTimeout

Defines a time limit, which should be used when waiting for async tasks like async format validators to perform their validation, before the validation fails with an `ASYNC_TIMEOUT` error.

validator = new ZSchema({
asyncTimeout: 2000

noEmptyArrays

When true, validator will assume that minimum count of items in any `arrayis 1, except when ``minItems: 0``` is explicitly defined.

validator = new ZSchema({
noEmptyArrays: true

noEmptyStrings

When true, validator will assume that minimum length of any string to pass type `stringvalidation is 1, except when ``minLength: 0``` is explicitly defined.

validator = new ZSchema({
noEmptyStrings: true

noTypeless

When true, validator will fail validation for schemas that don't specify a `type` of object that they expect.

validator = new ZSchema({
noTypeless: true

noExtraKeywords

When true, validator will fail for schemas that use keywords not defined in JSON Schema specification and doesn't provide a parent schema in `$schema` property to validate the schema.

validator = new ZSchema({
noExtraKeywords: true

assumeAdditional

When true, validator assumes that additionalItems/additionalProperties are defined as false so you don't have to manually fix all your schemas.

validator = new ZSchema({
assumeAdditional: true

When an array, validator assumes that additionalItems/additionalProperties are defined as false, but allows some properties to pass.

validator = new ZSchema({
assumeAdditional: ["$ref"]

forceAdditional

When true, validator doesn't validate schemas where additionalItems/additionalProperties should be defined to either true or false.

validator = new ZSchema({
forceAdditional: true

forceItems

When true, validator doesn't validate schemas where `itemsare not defined for ``array``` type schemas. This is to avoid passing anything through an array definition.

validator = new ZSchema({
forceItems: true

forceMinItems

When true, validator doesn't validate schemas where `minItemsis not defined for ``array``` type schemas. This is to avoid passing zero-length arrays which application doesn't expect to handle.

validator = new ZSchema({
forceMinItems: true

forceMaxItems

When true, validator doesn't validate schemas where `maxItemsis not defined for ``array``` type schemas. This is to avoid passing arrays with unlimited count of elements which application doesn't expect to handle.

validator = new ZSchema({
forceMaxItems: true

forceMinLength

When true, validator doesn't validate schemas where `minLengthis not defined for ``string``` type schemas. This is to avoid passing zero-length strings which application doesn't expect to handle.

validator = new ZSchema({
forceMinLength: true

forceMaxLength

When true, validator doesn't validate schemas where `maxLengthis not defined for ``string``` type schemas. This is to avoid passing extremly large strings which application doesn't expect to handle.

validator = new ZSchema({
forceMaxLength: true

forceProperties

When true, validator doesn't validate schemas where `propertiesor ``patternProperties` is not defined forobject`` type schemas. This is to avoid having objects with unexpected properties in application.

validator = new ZSchema({
forceProperties: true

ignoreUnresolvableReferences

When true, validator doesn't end with error when a remote reference is unreachable. This setting is not recommended in production outside of testing.

validator = new ZSchema({
ignoreUnresolvableReferences: true

strictUris

When true, all strings of format `uri` must be an absolute URIs and not only URI references. See more details in this issue.

validator = new ZSchema({
strictUris: true

strictMode

Strict mode of z-schema is currently equal to the following:

this.options.strictMode === true) {
this.options.forceAdditional  = true;
this.options.forceItems       = true;
this.options.forceMaxLength   = true;
this.options.forceProperties  = true;
this.options.noExtraKeywords  = true;
this.options.noTypeless       = true;
this.options.noEmptyStrings   = true;
this.options.noEmptyArrays    = true;

avascript
validator = new ZSchema({
strictMode: true

breakOnFirstError

By default, z-schema stops validation after the first error is found. With this you can tell it to continue validating anyway:

validator = new ZSchema({
breakOnFirstError: false

reportPathAsArray

Report error paths as an array of path segments instead of a string:

validator = new ZSchema({
reportPathAsArray: true

ignoreUnknownFormats

By default, z-schema reports all unknown formats, formats not defined by JSON Schema and not registered using ZSchema.registerFormat, as an error. But the JSON Schema specification says that validator implementations “they SHOULD offer an option to disable validation” for format. That being said, setting this option to true will disable treating unknown formats as errlrs

validator = new ZSchema({
ignoreUnknownFormats: true

customValidator

Warning: Use only if know what you are doing. Always consider using custom format before using this option.

Register function to be called as part of validation process on every subshema encounter during validation.

Let's make a real-life example with this feature. Imagine you have number of transactions:


"fromId": 1034834329,
"toId": 1034834543,
"amount": 200

So you write the schema:


"type": "object",
"properties": {
    "fromId": {
        "type": "integer"
    },
    "toId": {
        "type": "integer"
    },
    "amount": {
        "type": "number"
    }
}

But how to check that fromId and toId are never equal. In JSON Schema Draft4 there is no possibility to do this. Actually, it's easy to just write validation code for such simple payloads. But what if you have to do the same check for many objects in different places of JSON payload. One solution is to add custom keyword uniqueProperties with array of property names as a value. So in our schema we would need to add:

queProperties": [
"fromId",
"toId"

To teach z-schema about this new keyword we need to write handler for it:

tion customValidatorFn(report, schema, json) {
// check if our custom property is present
if (Array.isArray(schema.uniqueProperties)) {
    var seenValues = [];
    schema.uniqueProperties.forEach(function (prop) {
        var value = json[prop];
        if (typeof value !== 'undefined') {
            if (seenValues.indexOf(value) !== -1) {
                // report error back to z-schema core
                report.addCustomError("NON_UNIQUE_PROPERTY_VALUE",
                    "Property \"{0}\" has non-unique value: {1}",
                    [prop, value], null, schema.description);
            }
            seenValues.push(value)
        }
    });
}


validator = new ZSchema({
// register our custom validator inside z-schema
customValidator: customValidatorFn

Let's test it:

data = {
fromId: 1034834346,
toId: 1034834346,
amount: 50


dator.validate(data, schema);
ole.log(validator.getLastErrors())
{ code: 'NON_UNIQUE_PROPERTY_VALUE',
  params: [ 'toId', 1034834346 ],
  message: 'Property "toId" has non-unique value: 1034834346',
  path: '#/',
  schemaId: undefined } ]

Note: before creating your own keywords you should consider all compatibility issues.

Benchmarks

So how does it compare to version 2.x and others?

NOTE: these tests are purely orientational, they don't consider extra features any of the validator may support and implement

rawgithub.com/zaggino/z-schema/master/benchmark/results.html

Contributors

Thanks for contributing to:

and to everyone submitting issues on GitHub


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.