Giter Club home page Giter Club logo

z-schema's Issues

type coercion

In the same way you can register a validator, would it be possible to register a coercion function? The idea would be if you have a field you know is a timestamp, you could coerce it to a Date object, or if you had an attribute that was an array of Users which you have a class constructor for, you could have z-schema convert those to your local type.

Validate json by schema name

Hi, is there ability to cache schema by setRemoteReference and next - validate by it's uri? For example:

ZSchema.setRemoteReference('http://localhost:1234/integer.json', fileContent);
ZSchema.validate(myJsonData, 'http://localhost:1234/integer.json', function () {...})

Cheers

Error paths as Array

What do you think about enabling, via some configuration, the representation of error paths? On the one hand, I like the JSON Pointer syntax for presentation but on the other, I find an array of path segments to be much easier to work with from a programmatic perspective.

noTypeless behaviour

The compiler throws a schema validation error when noTypeless is set to true and instead of the type keyword any of the keywords oneOf, anyOf, not, $ref are present.

Is this the desired behaviour ? I think it would be more convenient if the error is not thrown if any one of those keywords are present on the schema since they all essentially define what the type of the object should be.

Trailing slashes in schema id breaks $ref

I'm not sure if this is related to #44 but I used almost the same test to reproduce this issue. Long story short, if your schema id ends with a #, references to the schema by id result in an UNRESOLVABLE_REFERENCE:

var ZSchema = require('z-schema');
var validator = new ZSchema();
var schemaA = {
  id: 'schemaA#',
  type: 'string'
};
var schemaB = {
  id: 'schemaB#',
  properties: {
    a: {
      // '$ref': 'schemaA' // Fails
      '$ref': 'schemaA#' // Fails
    }
  }
};
var result = validator.compileSchema([schemaA, schemaB]);

if (result === false) {
  console.log(validator.getLastErrors());
}

The output of this is:

[ { code: 'UNRESOLVABLE_REFERENCE',
    params: [ 'schemaB#schemaA#' ],
    message: 'Reference could not be resolved: schemaB#schemaA#',
    path: '#/properties/a' } ]

If I remove the trailing # from the id, everything works fine:

var ZSchema = require('z-schema');
var validator = new ZSchema();
var schemaA = {
  id: 'schemaA',
  type: 'string'
};
var schemaB = {
  id: 'schemaB',
  properties: {
    a: {
      // '$ref': 'schemaA' // Works
      '$ref': 'schemaA#' // Works
    }
  }
};
var result = validator.compileSchema([schemaA, schemaB]);

if (result === false) {
  console.log(validator.getLastErrors());
}

use `id` attribute during compilation to avoid future remote lookups

I'm working on a project that is using JSON schema. I currently set the id attribute of my schema to the URI that they will be eventually deployed to, just like the upstream IETF draft schema: http://json-schema.org/draft-04/schema

Would it be possible to feed multiple schema into a single validator instance and have it use the id attributes to build a local map of available schema?

My hope is that by feeding enough local schema into a validator, I can avoid all remote lookups. I haven't actually deployed my new JSON schema yet, and the remote lookups are making testing somewhat inconvenient.

Recompiling schemas results in 'Reference could not be resolved'

One of the projects I'm working on has a handful of schema files that get combined together to validate a complete JSON payload but there is also a need/desire to be able to treat these schema files individually and validate a JSON payload fragment. Below is an example structure:

var schemaCombinations = {
  'authorizationObject.json': [
    oauth2GrantType, // 'oauth2GrantType.json
    authorizationObject // 'authorizationObject.json
  ],
  'infoObject.json': [
    infoObject // infoObject.json
  ],
  'oauth2GrantType.json': [
    oauth2GrantType // oauth2GrantType.json
  ],
  'resourceObject.json': [
    resourceObject // resourceObject.json
  ],
  'resourceListing.json': [
    resourceObject, // resourceObject.json
    infoObject, // infoObject.json
    oauth2GrantType, // oauth2GrantType.json
    authorizationObject, // authorizationObject.json
    resourceListing // resourceListing.json
  ]
};

So each of these schema combinations represent the array of schema fragments to compile for the corresponding schema file to be valid. So each array is basically a list of dependencies, including itself.

If I had code to create a validator for each schema file, the first 4 compile just fine but the last one fails due to the following references not resolving: resourceObject.json, infoObject.json and authorizationObject.json. I'm not sure why that would happen. On a whim, I updated the same code to avoid building the first four validators and only build the last one and it works. Below is the code to replicate this. To reproduce the current problem, which happens when all 5 validators are created in the same program, run it as-is. To see the scenario where the failing validator compiles properly when the first four validators are not created prior, comment out Block One and uncomment Block Two.

'use strict';

var ZSchema = require('z-schema');
var resourceObject = {
  'id': 'resourceObject.json',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'type': 'object',
  'required': [ 'path' ],
  'properties': {
        'path': { 'type': 'string', 'format': 'uri' },
    'description': { 'type': 'string' }
  },
  'additionalProperties': false
};
var infoObject = {
  'id': 'infoObject.json',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'description': 'info object (section 5.1.3)',
  'type': 'object',
  'required': [ 'title', 'description' ],
  'properties': {
    'title': { 'type': 'string' },
    'description': { 'type': 'string' },
    'termsOfServiceUrl': { 'type': 'string', 'format': 'uri' },
    'contact': { 'type': 'string', 'format': 'email' },
    'license': { 'type': 'string' },
    'licenseUrl': { 'type': 'string', 'format': 'uri' }
  },
  'additionalProperties': false
};
var oauth2GrantType = {
  'id': 'oauth2GrantType.json',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'type': 'object',
  'minProperties': 1,
  'properties': {
    'implicit': { '$ref': '#/definitions/implicit' },
    'authorization_code': { '$ref': '#/definitions/authorizationCode' }
  },
  'definitions': {
    'implicit': {
      'type': 'object',
      'required': [ 'loginEndpoint' ],
      'properties': {
        'loginEndpoint': { '$ref': '#/definitions/loginEndpoint' },
        'tokenName': { 'type': 'string' }
      },
      'additionalProperties': false
    },
    'authorizationCode': {
      'type': 'object',
      'required': [ 'tokenEndpoint', 'tokenRequestEndpoint' ],
      'properties': {
        'tokenEndpoint': { '$ref': '#/definitions/tokenEndpoint' },
        'tokenRequestEndpoint': { '$ref': '#/definitions/tokenRequestEndpoint' }
      },
      'additionalProperties': false
    },
    'loginEndpoint': {
      'type': 'object',
      'required': [ 'url' ],
      'properties': {
        'url': { 'type': 'string', 'format': 'uri' }
      },
      'additionalProperties': false
    },
    'tokenEndpoint': {
      'type': 'object',
      'required': [ 'url' ],
      'properties': {
        'url': { 'type': 'string', 'format': 'uri' },
        'tokenName': { 'type': 'string' }
      },
      'additionalProperties': false
    },
    'tokenRequestEndpoint': {
      'type': 'object',
      'required': [ 'url' ],
      'properties': {
        'url': { 'type': 'string', 'format': 'uri' },
        'clientIdName': { 'type': 'string' },
        'clientSecretName': { 'type': 'string' }
      },
      'additionalProperties': false
    }
  }
};
var authorizationObject = {
  'id': 'authorizationObject.json',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'type': 'object',
  'additionalProperties': {
    'oneOf': [
      {
        '$ref': '#/definitions/basicAuth'
      },
      {
        '$ref': '#/definitions/apiKey'
      },
      {
        '$ref': '#/definitions/oauth2'
      }
    ]
  },
  'definitions': {
    'basicAuth': {
      'required': [ 'type' ],
      'properties': {
        'type': { 'enum': [ 'basicAuth' ] }
      },
      'additionalProperties': false
    },
    'apiKey': {
      'required': [ 'type', 'passAs', 'keyname' ],
      'properties': {
        'type': { 'enum': [ 'apiKey' ] },
        'passAs': { 'enum': [ 'header', 'query' ] },
        'keyname': { 'type': 'string' }
      },
      'additionalProperties': false
    },
    'oauth2': {
      'type': 'object',
      'required': [ 'type', 'grantTypes' ],
      'properties': {
        'type': { 'enum': [ 'oauth2' ] },
        'scopes': {
          'type': 'array',
          'items': { '$ref': '#/definitions/oauth2Scope' }
        },
        'grantTypes': { '$ref': 'oauth2GrantType.json' }
      },
      'additionalProperties': false
    },
    'oauth2Scope': {
      'type': 'object',
      'required': [ 'scope' ],
      'properties': {
        'scope': { 'type': 'string' },
        'description': { 'type': 'string' }
      },
      'additionalProperties': false
    }
  }
};
var resourceListing = {
  'id': 'resourceListing.json',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'type': 'object',
  'required': [ 'swaggerVersion', 'apis' ],
  'properties': {
    'swaggerVersion': { 'enum': [ '1.2' ] },
    'apis': {
      'type': 'array',
      'items': { '$ref': 'resourceObject.json' }
    },
    'apiVersion': { 'type': 'string' },
    'info': { '$ref': 'infoObject.json' },
    'authorizations': { '$ref': 'authorizationObject.json' }
  }
};

var schemaCombinations = {
  'authorizationObject.json': [
    oauth2GrantType,
    authorizationObject
  ],
  'infoObject.json': [
    infoObject
  ],
  'oauth2GrantType.json': [
    oauth2GrantType
  ],
  'resourceObject.json': [
    resourceObject
  ],
  'resourceListing.json': [
    resourceObject,
    infoObject,
    oauth2GrantType,
    authorizationObject,
    resourceListing
  ]
};

// Block One
Object.keys(schemaCombinations).forEach(function (name) {
  var validator = new ZSchema({sync: true});
  var toCompile = schemaCombinations[name];

  try {
    validator.compileSchema(toCompile);

    console.log(name +': success');
  } catch (err) {
    var vError = validator.getLastError();

    if (!vError.errors) {
      vError = err;
    }

    console.log(name +': failure');

    if (vError.errors) {
      vError.errors.forEach(function (error) {
        console.log('  ' + error.message);
      });
    } else {
      console.log('  ' + vError.message);
    }
  }
});

// Block Two
// new ZSchema({sync: true}).compileSchema(schemaCombinations['resourceListing.json']);

"$schema" keyword fails validation

Steps to reproduce:

  1. start node REPL
  2. execute the following code:
var schema = {
  "$schema": "http://json-schema.org/schema#",
  "properties": { "text": { "type": "string" } },
  "type": "object"
};
var json = { "text": "o"};
require("z-schema").validate(json, schema, console.log);

Expected:

Successful validation.

Actual:

.../node_modules/z-schema/src/ZSchema.js:318
                    throw new Error('Not a JSON data at: ' + url + ', ' + e);
                          ^
Error: Not a JSON data at: http://json-schema.org/schema, SyntaxError: Unexpected end of input
    at returnSchemaFromString (/Users/abj/Documents/LoveThis/git/antigua_api/service-dym/test/node_modules/z-schema/src/ZSchema.js:318:27)
    at IncomingMessage.<anonymous> (/Users/abj/Documents/LoveThis/git/antigua_api/service-dym/test/node_modules/z-schema/src/ZSchema.js:344:21)
    at IncomingMessage.EventEmitter.emit (events.js:117:20)
    at _stream_readable.js:920:16
    at process._tickCallback (node.js:415:13)

Reference:

benchmarks addition?

Hi @zaggino

I recently created yet another javascript json-schema library called jjv, hosted here:
https://github.com/acornejo/jjv

Due to security and performance reasons, it does not support downloading remote references. Aside from that it should be draft4 compatible (it passes all appropriate tests).

I haven't had time to create a benchmark script, but I would love to see how it compares with other available libraries.

Would you mind adding jjv to your list in your benchmark wiki? I believe it should be fairly easy to do, the following snippet should do the trick:

Tester.registerValidator({
  name: 'jjv',
  setup: function () {
    return jjv();
  },
  test: function (instance, json, schema) { 
    return instance.validate(schema, json) === null;
  }
})

The above assumes you did var jjv=require('jjv'); and that you added jjv 0.3.0 to the npm package list.

Thanks

missing files in 1.4.0

not sure if I am going crazy, but when I try to NPM install this library, no code is actually included in the package. There's no .js files inside node_modules/z-schema and requiring the library doesn't work.

afischer-mba ~ $ npm install z-schema
npm http GET https://registry.npmjs.org/z-schema
npm http 304 https://registry.npmjs.org/z-schema
npm http GET https://registry.npmjs.org/q
npm http 304 https://registry.npmjs.org/q
[email protected] node_modules/z-schema
└── [email protected]
afischer-mba ~ $ ls node_modules/z-schema/
LICENSE     README.md   node_modules    package.json
afischer-mba ~ $ node
> require('z-schema')
Error: Cannot find module 'z-schema'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at repl:1:2
    at REPLServer.self.eval (repl.js:111:21)
    at Interface.<anonymous> (repl.js:250:12)
    at Interface.EventEmitter.emit (events.js:93:17)
    at Interface._onLine (readline.js:199:10)
    at Interface._line (readline.js:517:8)

Include description (if any) if property of type string with pattern fails

First of all, awesome library :) we are starting to use it and really like the robustness and how easy to use it is.

Now, onto the issue. If we have the following (partial) schema:

"name": {
  "type": "string",
  "pattern": "^[^<>]*$",
  "description": "Name of the client. Invalid characters are < and >."
},

It would be useful to get a human friendly representation of the error which is better that the regex. Currently the error looks like (in z-schema 2.x.x but is seems to provide the same info in 3.x.x):

{ code: 'PATTERN',
  message: 'String does not match pattern: ^[^<>]*$',
  path: '#/name',
  params: { pattern: '^[^<>]*$' } }

Ideally we would get:

{ code: 'PATTERN',
  message: 'String does not match pattern: ^[^<>]*$',
  path: '#/name',
  params: { pattern: '^[^<>]*$', description: 'Name of the client. Invalid characters are < and >.' } }

This seems to only require a small change at https://github.com/zaggino/z-schema/blob/master/src/JsonValidation.js#L77 but would be really useful for reporting errors back to users, e.g. when using JSON schema to validate API calls.

Thoughts?

How to register several schemas with an id?

I'm not sure if this question is already answered.

If I have 3 schemas in memory, each of them has an id attribute, one of them is the main schema.

How can I do the following with z-schema:

  1. register all 3 schemas with z-schema validator
  2. check if there are unresolved references
  3. validate objects against one of the 3 schemas

I can do this with other libraries but do not see how to do this with z-schema. setRemoteReference needs an url, which I'm not willing to provide because each of the schemas has an id attribute.

Here are the schemas, for example:

var schemaA = {id: "schemaA", type: "integer"};
var schemaB = {id: "schemaB", type: "string"};
var mainSchema = {
    id: "mainSchema",
    type: "object",
    properties: {
        a: {"$ref": "schemaA"},
        b: {"$ref": "schemaB"},
        c: {"enum": ["C"]}
    }
};

Nested hierarchy without explicit leaf

Hello,
I have a nested hierarchy and I don't want to explicitly define the last item as was done in #22. When I remove the oneOf construct it seems to end in an infinite loop.

This is the json/schema exhibiting the issue:
JSON

{ "is_start": true,
    "hierarchy": {
        "is_and": false,
        "filters": [
            {
                "is_and": false,
                "filters": [
                    {
                        "is_and": true,
                        "filters": [
                            {
                                "is_and": true,
                                "filters": [
                                    {
                                        "is_and": true,
                                        "filters": [
                                            {
                                                "is_and": true,
                                                "filters": [
                                                    {
                                                        "is_and": true,
                                                        "filters": []
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }}

SCHEMA

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product set",
    "is_start": "boolean",
    "hierarchy": {
        "$ref": "#/definitions/recursion"
    },
    "definitions": {
        "recursion": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "is_and": {
                    "type": "boolean"
                },
                "filters": {
                    "type": "array",
                    "additionalItems": false,
                    "items": {
                        "$ref": "#/definitions/recursion"
                    }
                }
            }
        }
    }
}

The "validateSchema" method with callback function doesn't actually validate.

It looks like the "validateSchema" method doesn't actually validate the given schema:

var ZSchema = require('z-schema');
var validator = new ZSchema();
validator.validateSchema('bogus schema here', function(err, report) {
  if (err) throw err;
  console.log(report); // { valid: true, errors: [], warnings: [] }
});

sync validate method doesn't work

I just tried to follow your example, using [var validator = new ZSchema({ sync: true }); ] and I have this whole Failure Trace...

TypeError: Object true has no method 'forEach'
at ZSchema.InstanceValidators.required (\node_modules\z-schema\src\ZSchema.js:1905:29)
at step1 (\node_modules\z-schema\src\ZSchema.js:1223:48)
at Object.Utils.forEach (\node_modules\z-schema\src\ZSchema.js:195:34)
at ZSchema._validateObject (\node_modules\z-schema\src\ZSchema.js:1244:19)
at ZSchema.<anonymous> (\node_modules\z-schema\src\ZSchema.js:1383:26)
at Array.forEach (native)
at ZSchema.<anonymous> (\node_modules\z-schema\src\ZSchema.js:1380:15)
at Object.Utils.forEach (\node_modules\z-schema\src\ZSchema.js:195:34)
at ZSchema._recurseObject (\node_modules\z-schema\src\ZSchema.js:1354:15)
at step2 (\node_modules\z-schema\src\ZSchema.js:1232:29)
at ZSchema._validateObject (\node_modules\z-schema\src\ZSchema.js:1245:13)
at ZSchema.validate (\node_modules\z-schema\src\ZSchema.js:792:18)

noTypeless behavior when using anyof

I think this case should be valid, but currently throws an error. The current implementation only looks for type on the anyOf schemas and not the parent.

type: 'object',
properties: {
    'prop1': {...}
    'prop2': {...},
},
anyOf: [
    {
        required: ['prop1']
    },
    {
        required: ['prop2']
    }
]

Validation errors on non-required fields

Hi,

First of all, thanks for this great library!
I've encountered some problems validating a schema with optional/non-required properties.
I get this error:

errors: Array[2]
0: ValidationError
code: "FORMAT"
message: "date format validation failed: "
path: "#/date_of_birth"
1: ValidationError
code: "PATTERN"
message: "String does not match pattern: ^[1-9]{1}[0-9]{3} ?[A-Z]{2}$"
params: Object
path: "#/postcode"
valid: false

on this schema:
"website_users":
{
"$schema": "http://json-schema.org/schema#",
"description": "Schema for the website users context",
"type": "object",
"self": {
"vendor": "xxxx",
"name": "website_users",
"format": "jsonschema",
"version": "1-0-0"
},
"properties": {

        "date_of_birth": {
            "type": "string",
            "format": "date" 
        },

        "dealer_postcode": {
            "type": "string",
            "pattern": "^[1-9]{1}[0-9]{3} ?[A-Z]{2}$"
        },
        "email": {
            "type": "string",
            "maxLength": 128
        },
        "email_id": {
            "type": "string",
            "maxLength": 64
        },
        "firstname": {
            "type": "string",
            "maxLength": 64
        },
        "gender": {
            "type": "string", "enum":["man","vrouw"]
        },
        "housenumber": {
            "type": "string",
            "maxLength": 16
        },
        "initials": {
            "type": "string",
            "maxLength": 8
        },
        "kvk_nummer": {
            "type": "string",
            "maxLength": 32
        },
        "language": {
            "type": "string",
            "maxLength": 16
        },
        "lastname": {
            "type": "string",
            "maxLength": 64
        },

        "phonenumber": {
            "type": "string",
            "maxLength": 32
        },
        "postcode": {
            "type": "string",
            "pattern": "^[1-9]{1}[0-9]{3} ?[A-Z]{2}$"
        },
        "street": {
            "type": "string",
            "maxLength": 64
        },
        "tussenvoegsel": {
            "type": "string",
            "maxLength": 16
        },
        "user_id": {
            "type": "string",
            "maxLength": 32
        }
    },
    "required": ["email"],
    "additionalProperties": false
}
  • This is just a fragment of the complete json schema.

I understand that the validation fails on these fields (because they are empty) but they are optional.

Thanks in advance!

Proper way to reference schema files in same directory as root schema file?

Hi, I am working with schema files on a local filesystem, and am wondering how a schema file that is referenced should be entered in the main schema file?

example:

"schemas":{
  "schemaA":{
     "description":"description",
     "id":"schemaA",
     "type":"object",
     "properties":{
        "payments":{
           "type":"array",
           "description":"description",
           "items":{
              "$ref":"file-to-ref-same-directory.json"
           }
        }

What format should the value for $ref be if the json file is in the same directory as the primary json file?

Thanks!

Maximum call stack exceeded when compiling array of schemas

I have an application that uses Swagger 1.2 schema files. Their schema files are not perfect but I've been able to work around them using jjv. I want to use z-schema and I've started writing a few tests to see how I'd load the schema files I need. I've run into a problem where a Maximum call stack exceeded happens with the following code (Warning, it's long but the purpose was to give you a copy/paste test instead of you having to download the Swagger 1.2 schema files yourself.). When I run the code, I get the following error:

/private/tmp/testing/node_modules/z-schema/src/SchemaCache.js:38
    if (Array.isArray(schema)) {
              ^
RangeError: Maximum call stack size exceeded

I'm using [email protected]. Here is the code that creates the error above:

var dataTypeBaseJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/dataTypeBase.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Data type fields (section 4.3.3)",
  "type": "object",
  "oneOf": [
    {
      "required": [
        "type"
      ]
    },
    {
      "required": [
        "$ref"
      ]
    }
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "$ref": {
      "type": "string"
    },
    "format": {
      "type": "string"
    },
    "defaultValue": {
      "not": {
        "type": [
          "array",
          "object",
          "null"
        ]
      }
    },
    "enum": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "uniqueItems": true,
      "minItems": 1
    },
    "minimum": {
      "type": "string"
    },
    "maximum": {
      "type": "string"
    },
    "items": {
      "$ref": "#/definitions/itemsObject"
    },
    "uniqueItems": {
      "type": "boolean"
    }
  },
  "dependencies": {
    "format": {
      "oneOf": [
        {
          "properties": {
            "type": {
              "enum": [
                "integer"
              ]
            },
            "format": {
              "enum": [
                "int32",
                "int64"
              ]
            }
          }
        },
        {
          "properties": {
            "type": {
              "enum": [
                "number"
              ]
            },
            "format": {
              "enum": [
                "float",
                "double"
              ]
            }
          }
        },
        {
          "properties": {
            "type": {
              "enum": [
                "string"
              ]
            },
            "format": {
              "enum": [
                "byte",
                "date",
                "date-time"
              ]
            }
          }
        }
      ]
    }
  },
  "definitions": {
    "itemsObject": {
      "oneOf": [
        {
          "type": "object",
          "required": [
            "$ref"
          ],
          "properties": {
            "$ref": {
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        {
          "allOf": [
            {
              "$ref": "#"
            },
            {
              "required": [
                "type"
              ],
              "properties": {
                "type": {},
                "format": {}
              },
              "additionalProperties": false
            }
          ]
        }
      ]
    }
  }
};
var modelsObjectJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/modelsObject.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "required": [
    "id",
    "properties"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "properties": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/propertyObject"
      }
    },
    "subTypes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "uniqueItems": true
    },
    "discriminator": {
      "type": "string"
    }
  },
  "dependencies": {
    "subTypes": [
      "discriminator"
    ]
  },
  "definitions": {
    "propertyObject": {
      "allOf": [
        {
          "not": {
            "$ref": "#"
          }
        },
        {
          "$ref": "dataTypeBase.json#"
        }
      ]
    }
  }
};
var oauth2GrantTypeJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/oauth2GrantType.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "minProperties": 1,
  "properties": {
    "implicit": {
      "$ref": "#/definitions/implicit"
    },
    "authorization_code": {
      "$ref": "#/definitions/authorizationCode"
    }
  },
  "definitions": {
    "implicit": {
      "type": "object",
      "required": [
        "loginEndpoint"
      ],
      "properties": {
        "loginEndpoint": {
          "$ref": "#/definitions/loginEndpoint"
        },
        "tokenName": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "authorizationCode": {
      "type": "object",
      "required": [
        "tokenEndpoint",
        "tokenRequestEndpoint"
      ],
      "properties": {
        "tokenEndpoint": {
          "$ref": "#/definitions/tokenEndpoint"
        },
        "tokenRequestEndpoint": {
          "$ref": "#/definitions/tokenRequestEndpoint"
        }
      },
      "additionalProperties": false
    },
    "loginEndpoint": {
      "type": "object",
      "required": [
        "url"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    },
    "tokenEndpoint": {
      "type": "object",
      "required": [
        "url"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "tokenName": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "tokenRequestEndpoint": {
      "type": "object",
      "required": [
        "url"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "clientIdName": {
          "type": "string"
        },
        "clientSecretName": {
          "type": "string"
        }
      },
      "additionalProperties": false
    }
  }
};
var authorizationObjectJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/authorizationObject.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "$ref": "#/definitions/basicAuth"
      },
      {
        "$ref": "#/definitions/apiKey"
      },
      {
        "$ref": "#/definitions/oauth2"
      }
    ]
  },
  "definitions": {
    "basicAuth": {
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "enum": [
            "basicAuth"
          ]
        }
      },
      "additionalProperties": false
    },
    "apiKey": {
      "required": [
        "type",
        "passAs",
        "keyname"
      ],
      "properties": {
        "type": {
          "enum": [
            "apiKey"
          ]
        },
        "passAs": {
          "enum": [
            "header",
            "query"
          ]
        },
        "keyname": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "oauth2": {
      "type": "object",
      "required": [
        "type",
        "grantTypes"
      ],
      "properties": {
        "type": {
          "enum": [
            "oauth2"
          ]
        },
        "scopes": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/oauth2Scope"
          }
        },
        "grantTypes": {
          "$ref": "oauth2GrantType.json#"
        }
      },
      "additionalProperties": false
    },
    "oauth2Scope": {
      "type": "object",
      "required": [
        "scope"
      ],
      "properties": {
        "scope": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "additionalProperties": false
    }
  }
};
var parameterObjectJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/parameterObject.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "allOf": [
    {
      "$ref": "dataTypeBase.json#"
    },
    {
      "required": [
        "paramType",
        "name"
      ],
      "properties": {
        "paramType": {
          "enum": [
            "path",
            "query",
            "body",
            "header",
            "form"
          ]
        },
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "required": {
          "type": "boolean"
        },
        "allowMultiple": {
          "type": "boolean"
        }
      }
    },
    {
      "description": "type File requires special paramType and consumes",
      "oneOf": [
        {
          "properties": {
            "type": {
              "not": {
                "enum": [
                  "File"
                ]
              }
            }
          }
        },
        {
          "properties": {
            "type": {
              "enum": [
                "File"
              ]
            },
            "paramType": {
              "enum": [
                "form"
              ]
            },
            "consumes": {
              "enum": [
                "multipart/form-data"
              ]
            }
          }
        }
      ]
    }
  ]
};
var operationObjectJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/operationObject.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "allOf": [
    {
      "$ref": "dataTypeBase.json#"
    },
    {
      "required": [
        "method",
        "nickname",
        "parameters"
      ],
      "properties": {
        "method": {
          "enum": [
            "GET",
            "POST",
            "PUT",
            "PATCH",
            "DELETE",
            "OPTIONS"
          ]
        },
        "summary": {
          "type": "string",
          "maxLength": 120
        },
        "notes": {
          "type": "string"
        },
        "nickname": {
          "type": "string",
          "pattern": "^[a-zA-Z0-9_]+$"
        },
        "authorizations": {
          "type": "object",
          "additionalProperties": {
            "type": "array",
            "items": {
              "$ref": "authorizationObject.json#/definitions/oauth2Scope"
            }
          }
        },
        "parameters": {
          "type": "array",
          "items": {
            "$ref": "parameterObject.json#"
          }
        },
        "responseMessages": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/responseMessageObject"
          }
        },
        "produces": {
          "$ref": "#/definitions/mimeTypeArray"
        },
        "consumes": {
          "$ref": "#/definitions/mimeTypeArray"
        },
        "deprecated": {
          "enum": [
            "true",
            "false"
          ]
        }
      }
    }
  ],
  "definitions": {
    "responseMessageObject": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "$ref": "#/definitions/rfc2616section10"
        },
        "message": {
          "type": "string"
        },
        "responseModel": {
          "type": "string"
        }
      }
    },
    "rfc2616section10": {
      "type": "integer",
      "minimum": 100,
      "maximum": 600,
      "exclusiveMaximum": true
    },
    "mimeTypeArray": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "mime-type"
      }
    }
  }
}
var apiDeclarationJson = {
  "id": "http://wordnik.github.io/schemas/v1.2/apiDeclaration.json#",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "required": [
    "swaggerVersion",
    "basePath",
    "apis"
  ],
  "properties": {
    "swaggerVersion": {
      "enum": [
        "1.2"
      ]
    },
    "apiVersion": {
      "type": "string"
    },
    "basePath": {
      "type": "string",
      "format": "uri",
      "pattern": "^https?://"
    },
    "resourcePath": {
      "type": "string",
      "format": "uri",
      "pattern": "^/"
    },
    "apis": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/apiObject"
      }
    },
    "models": {
      "type": "object",
      "additionalProperties": {
        "$ref": "modelsObject.json#"
      }
    },
    "produces": {
      "$ref": "#/definitions/mimeTypeArray"
    },
    "consumes": {
      "$ref": "#/definitions/mimeTypeArray"
    },
    "authorizations": {
      "$ref": "authorizationObject.json#"
    }
  },
  "additionalProperties": false,
  "definitions": {
    "apiObject": {
      "type": "object",
      "required": [
        "path",
        "operations"
      ],
      "properties": {
        "path": {
          "type": "string",
          "format": "uri-template",
          "pattern": "^/"
        },
        "description": {
          "type": "string"
        },
        "operations": {
          "type": "array",
          "items": {
            "$ref": "operationObject.json#"
          }
        }
      },
      "additionalProperties": false
    },
    "mimeTypeArray": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "mime-type"
      }
    }
  }
};
var ZSchema = require('z-schema');
var validator = new ZSchema();
var result = validator.compileSchema([
  dataTypeBaseJson,
  modelsObjectJson,
  oauth2GrantTypeJson,
  authorizationObjectJson,
  parameterObjectJson,
  operationObjectJson,
  apiDeclarationJson
]);

if (result === false) {
  console.dir(validator.getLastErrors());
}

There is no validation function for format "regex"

Having a schema with $schema: 'http://json-schema.org/draft-04/schema#', setting remote schema

ZSchema.setRemoteReference('http://json-schema.org/draft-04/schema',
  fs.readFileSync (path.join __dirname, 'json-schema-draft-04', 'schema.json'), 'utf8')

and validate something against that schema, leads to

{
  code: 'UNKNOWN_FORMAT',
  message: 'There is no validation function for format "regex"',
  path: '#/properties[pattern]',
  params: { format: 'regex' } 
} 

format 'hostname' doesn't work correctly

String '127.0.0.1' validates against format 'hostname' and 'ipv4' which is not correct!

{
  "ipAddress": "127.0.0.1"
}

must be ok against

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "ipAddress": {
      "type": "string",
      "oneOf": [
        {
          "format": "hostname"
        },
        {
          "format": "ipv4"
        },
        {
          "format": "ipv6"
        }
      ]
    }
  }
}

but is not with Z-Schema.

You can check with http://json-schema-validator.herokuapp.com/ or look at http://json-schema.org/example2.html. Also have a look at natesilva/jayschema#21.

Reason for creating this library?

I'd like to know why development of this library was started although there are JSON schema validation libraries out there? What are the features of this library which make z-schema different from other libraries (i.e. natesilva/jayschema)? Is it the Promises/A+ based API?

Use JSON pointer syntax for error path strings

Right now, the string path of an error is a mix of JSON Pointer and some JavaScript string you would eval. I would like to propose that error paths, when in string form (See #55), use JSON Pointer syntax. So instead of #/some/[1]/path[operation], it would be #/some/1/path/operation.

I ran across this while working on #55. If you'd like, I an submit a PR for this as well once the PR for #55 is completed.

Handle a Date instance?

I work mostly in Node and front-end javascript. I like Z-Schema, but it forces me to convert the date to a String, then back to a Date after validation. It's a little cumbersome because mongodb allows storing Date instances into the db. How could I extend or modify z-schema to handle a Date instance? Or could we add the functionality into Z-Schema?

registerFormat has no effect on validation result

I noticed today that my custom format is not having any effect on the end result. I always get successful validation. Is there more I need to do to register my custom format? Provide some kind of error message?

ZSchema.registerFormat('date-object', function (obj) {
    //return obj instanceof Date;
    return false;  // Still passes
});

ZSchema.registerFormat('object-id', function (obj) {
    //return obj instanceof ObjectID;
    return false;  // Still passes
});

Here is part of my schema:

'notes': {
    type: 'array',
    items: {
        type: 'object',
        properties: {
            'note': { type: 'string', maxLength: 2048 },
            'created': { type: 'object', format: 'date-object' },
            'createdBy': { type: 'string', maxLength: 161 },
            '_id': { type: 'object', format: 'object-id' }
        }
    }
}

Clarification on validating the URI format and the reason for strictUris mode.

Having a schema with $schema: 'http://json-schema.org/draft-04/schema#', setting remote schema

ZSchema.setRemoteReference('http://json-schema.org/draft-04/schema',
  fs.readFileSync (path.join __dirname, 'json-schema-draft-04', 'schema.json'), 'utf8')

and validate something against that schema, leads to

{
  code: 'FORMAT',
  message: 'uri format validation failed: schemaA',
  path: '#/id',
  params: { format: 'uri', error: 'schemaA' } 
}

If I remove $schema: 'http://json-schema.org/draft-04/schema#' from my schema validation is ok.

My schema is quite simple:

schemaA = {
    $schema: 'http://json-schema.org/draft-04/schema#',
    id: "schemaA",
    type: "object",
    properties: {
      a: {
        type: "integer"
      },
      b: {
        type: "string"
      }
    },
    required: ['a']
  };

If I change the id value from 'schemaA' to 'http://my.company.de/project#mainSchema' then validation is ok. Isn't 'schemaA' a valid URI ?

Extremely long validation time for complex object

Okay, if I validate this object it takes <1 ms.

{
    firstname: 'First',
    lastname: 'Last',
}

If I validate this object, it takes 32ms. What is happening that the ObjectID adds 31 ms processing time? Processing time goes up linearly, the more ObjectID's it has to check. Sometimes I need to check arrays of objects with ObjectIDs and that gets outrageous.

{
    _id: new ObjectID(),  // mongodb id
    firstname: 'First',
    lastname: 'Last',
}

expose schema validation methods

I've noticed that schema are automatically validated when you attempt to use them to validate data.

I'm writing unit tests for a project that uses JSON schema, and it would be terrific if I could access these validation methods easily to facilitate with my tests.

validation ok despite missing reference

{a: 4}

is validated successfully against

{
    $schema: 'http://json-schema.org/draft-04/schema#',
    id: "schemaA",
    type: "object",
    properties: {
      a: {
        type: "integer"
      },
      b: {
        type: "string"
      },
      c: {
        $ref: 'schemaB'
      }
    },
    required: ['a']
  }

Unexpected error if a $ref cannot be resolved

Running the following code under Node.js

var ZSchema, main, schemaA;
ZSchema = require("z-schema");

schemaA = {
    $schema: 'http://json-schema.org/draft-04/schema#',
    id: "schemaA",
    type: "object",
    properties: {a: {type: "integer"}, b: {type: "string"}, c: {$ref: 'schemaB'}},
    required: ['a', 'c']
  };

var json, schema;
    schema = schemaA;
    json = {a: 4, c: 4};
    console.info("#1: validate ...");
    ZSchema.validate(json, schema, function(err, report) {
      var _ref;
      if (err) {
        console.error("... not valid!");
        if ("errors" in err) {
          console.error(err.errors);
        }
        return;
      }
      console.info("... OK");
      if ((_ref = report.warnings) != null ? _ref.length : void 0) {
        return console.warn(report.warnings);
      }
    });

results to the following console output, which I don't expect:

#1: validate ...
... not valid!
[ { code: 'INVALID_TYPE',
    message: 'invalid type: integer (expected object)',
    path: '#/c',
    params: { expected: 'object', type: 'integer' } } ]

nested hierarchy

Hi,

I have nested hierarchy like this:

{
"is_and": false,
"filters": [
{
"is_and": false,
"filters": [
{
"is_and": true,
"filters": [
{
"is_and": true,
"filters": [
{
"is_and": true,
"filters": [
{
"is_and": true,
"filters": [
{
"text": 'ABC',
"is_last": true,
"filters": [

                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

]
}

Now i want to validate the above json schema with self referencing but issue is that the last item in nested hierarchy has different properties & filter object being empty too, so having trouble for terminating the last item in hierarchy.

anyone suggest short validation rule.

Thanks

Clarification on the schema/reference id and the trailing hash

The Plugging this into our main schema example of the JSON Schema - Advanced Example shows an example of a $ref with a trailing # at the end. If I have a schema id of mySchema and I reference it from another document with a $ref of mySchema#, I'd expect that to work. But with z-schema, this does not work. For the reference to work, I either have to change my schema.id to mySchema# or change my $ref to be mySchema. Below is an example that will result in an unresolvable reference. Is the # suppose to be significant in the id/reference?

var ZSchema = require('z-schema');
var validator = new ZSchema({sync: true});
var schemaA = {
  id: 'schemaA',
  type: 'string'
};
var schemaB = {
  id: 'schemaB',
  properties: {
    a: {
      // '$ref': 'schemaA' // Works
      '$ref': 'schemaA#' // Fails
    }
  }
};

try {
  validator.compileSchema([schemaA, schemaB]);
} catch (err) {
  var vError = validator.getLastError();

  if (vError && vError.valid === false) {
    console.log(validator.getLastError());
  } else {
    throw err;
  }
}

Partial validation & tying additional validations to partial validations

I'm still pretty new to JSON schema, but looking around at the other JSON Schema validation libraries out there, I have yet to find one that will support my use case. However judging by the z-schema API, it appears that you may be the most open to the ideas I have in mind were I to fork and submit pull requests.

Basically, I'm looking to add support for two features:

(1) the ability to register additional non-JSON-schema validations. For example, when validating an npm package.json file, it's easy to define a validation that checks if a string is a valid path. However, I would also like to be able to register a validation that checks if those paths actually exist on disk relative to the location of the package.json file itself. Another example would be checking if a homepage URL doesn't return a 404 not found error.

I reckon this feature would be implementable by allowing you to register pre and post validation functions that receive the value of the property being validated and returning true if additional validations succeed or errors otherwise. These functions would need access to the context in which they are called (so that they can get access via closures to details such as the directory in which a package.json exists).

(2) partial validation for performance reasons. For example, if I have already loaded a JSON into memory and validated it on load, I don't want to completely revalidate it on write. Instead I'd like the ability to only validate the properties that I am modifying.

validator.validate(partialJSON, "lib://package.json#/definitions/dependency-map", function(err, result) {
  if (err) { /* ..  handle err ... */ }
  /* ... add partialJSON to full JSON and write to disk ... */
});

or alternatively schemas could have method support for getting definitions, like so:

compiledSchema.getDefinition("dependency-map")

or a validatePartial method could be added to ZSchema like so:

validator.validate(partialJSON, schema, definitionName, function(err, result) {
  if (err) { /* ..  handle err ... */ }
  /* ... add partialJSON to full JSON and write to disk ... */
});

For this second feature the following features would be valuable:

As far as I can tell, suggestion two seems reasonable, but the first suggestion might be better as a separate module built on top of your validator or another one. However, to build feature (1) on top, it would be immensely useful to have partial validation.

I just started looking through the source and I'm still thinking through how these might be implementable, but I wanted to get your thoughts on them. Would you be open to accepting pull requests for these features?

Strict mode for email/domain names

The email format is pretty strict about checking for global Top-Level Domains:
(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])

The JSON schema spec is less strict about email, just saying they should comply with:
http://xml2rfc.ietf.org/public/rfc/html/rfc5322.html#addrspec

Although this seems useful the majority of the time, there are two problems with maintaining a strict list of gTLDs:

  • ICANN has been rapidly granting new gTLDs. According to ICANN:

The expansion of generic Top-Level Domains (e.g. .COM, .ORG, .NET) in the Domain Name System is underway. Over 1,300 new names or "strings" could become available in the next few years.
http://newgtlds.icann.org/en/program-status/delegated-strings

  • Emails addresses that are valid on intranets, pseudo-top-level-domains, or other networks that use TLDs that are not delegated by ICANN.

FYI: The email address I was testing was [email protected].

missing references?

hi @zaggino ,
i have a question/issue.. having schema (taken from your example) formatted as object :

{
  "id": "root.json",
  "person": {
    "id": "personDetails",
    "type": "object",
    "properties": {
      "firstName": {
        "type": "string"
      },
      "lastName": {
        "type": "string"
      }
    },
    "required": ["firstName", "lastName"]
  },
  "addr": {
    "id": "addressDetails",
    "type": "object",
    "properties": {
      "street": {
        "type": "string"
      },
      "city": {
        "type": "string"
      }
    },
    "required": ["street", "city"]
  },
  "peraddr": {
    "id": "personWithAddress",
    "allOf": [{
      "$ref": "#personDetails"
    }, {
      "$ref": "#addressDetails"
    }, {
      "$ref": "#/yy"
    }, {
      "$ref": "#xx"
    }]
  }

and code:

  allSchemasValid = validator.validateSchema(rootschema);
  // allSchemasValid === flase

  comp_res = validator.compileSchema(rootschema);
  // comp_res === flase

  err = validator.getLastErrors()
/*
err == [
 {
  code: "UNRESOLVABLE_REFERENCE"
  message: "Reference could not be resolved: #/yy"
  params: [  "#/yy" ]
  path: "#/peraddr/allOf/2"
 }
]
*/

miss =validator.getMissingReferences()
/*
miss == [
""
]
*/

is validator.getMissingReferences() return as it should be?

'Maximum call stack size exceeded' for self-referencing allOf+not

I'm trying to get z-schema to load the Swagger Schemas. I noticed that for the modelsObject.json, I was getting a Maximum call stack size exceeded. Below is a recipe that will reproduce the issue. schemaA corresponds to dataTypeBase.json and schemaB corresponds with modelsObject.json.

var schemaA = {
  'id': 'schemaA',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'description': 'Data type fields (section 4.3.3)',
  'type': 'object',
  'oneOf': [
    { 'required': [ 'type' ] },
    { 'required': [ '$ref' ] }
  ],
  'properties': {
    'type': { 'type': 'string' },
    '$ref': { 'type': 'string' },
    'format': { 'type': 'string' },
    'defaultValue': {
      'not': { 'type': [ 'array', 'object', 'null' ] }
    },
    'enum': {
      'type': 'array',
      'items': { 'type': 'string' },
      'uniqueItems': true,
      'minItems': 1
    },
    'minimum': { 'type': 'string' },
    'maximum': { 'type': 'string' },
    'items': { '$ref': '#/definitions/itemsObject' },
    'uniqueItems': { 'type': 'boolean' }
  },
  'dependencies': {
    'format': {
      'oneOf': [
        {
          'properties': {
            'type': { 'enum': [ 'integer' ] },
            'format': { 'enum': [ 'int32', 'int64' ] }
          }
        },
        {
          'properties': {
            'type': { 'enum': [ 'number' ] },
            'format': { 'enum': [ 'float', 'double' ] }
          }
        },
        {
          'properties': {
            'type': { 'enum': [ 'string' ] },
            'format': {
              'enum': [ 'byte', 'date', 'date-time' ]
            }
          }
        }
      ]
    }
  },
  'definitions': {
    'itemsObject': {
      'oneOf': [
        {
          'type': 'object',
          'required': [ '$ref' ],
          'properties': {
            '$ref': { 'type': 'string' }
          },
          'additionalProperties': false
        },
        {
          'allOf': [
            { '$ref': '#' },
            {
              'required': [ 'type' ],
              'properties': {
                'type': {},
                'format': {}
              },
              'additionalProperties': false
            }
          ]
        }
      ]
    }
  }
};
var schemaB = {
  'id': 'schemaB',
  '$schema': 'http://json-schema.org/draft-04/schema#',
  'type': 'object',
  'required': [ 'id', 'properties' ],
  'properties': {
    'id': { 'type': 'string' },
    'description': { 'type': 'string' },
    'properties': {
      'type': 'object',
      'additionalProperties': { '$ref': '#/definitions/propertyObject' }
    },
    'subTypes': {
      'type': 'array',
      'items': { 'type': 'string' },
      'uniqueItems': true
    },
    'discriminator': { 'type': 'string' }
  },
  'dependencies': {
    'subTypes': [ 'discriminator' ]
  },
  'definitions': {
    'propertyObject': {
      'allOf': [
        {
          'not': { '$ref': '#' }
        },
        {
          '$ref': 'schemaA'
        }
      ]
    }
  }
};
var ZSchema = require('z-schema');
var validator = new ZSchema({sync: true});

try {
  validator.compileSchema([schemaA, schemaB]);
} catch (err) {
  var vError = validator.getLastError();

  if (vError && vError.valid === false) {
    console.log(validator.getLastError());
  } else {
    throw err;
  }
}

References to draft4 subschema are not working

I've been trying to use Z-Schema to validate a schema for the Swagger 2 specification.

I'm getting this error:

Error: Use .setRemoteReference to download references in sync mode: http://json-schema.org/draft-04/schema

I've tried it as sync, async, and explicitly using setRemoteReference on a downloaded copy of the schema. None have worked.

I was able to get it to work by altering the host of the $ref (e.g. "json-schema.org" to "json-schema.orgx") and doing a setRemoteReference. So I'm speculating, but I think that the "json-schema.org" schemas are probably being treated specially and download is being skipped, but then can't be found when we refer to a subschema. Example:

"title": { "$ref": "http://json-schema.org/draft-04/schema#/properties/title" }

I created a gist with a frozen copy of the schema and sample you can try, or you can check out reverb/swagger-spec.

"links" warning in Hyper-Schema validation

Tries to validate simple hyper-schemas with empty links array, and got a warning telling me that links is unknown key despite I set $schema to hyper-schema url explicitly:

var ZSchema = require('z-schema');

var schema = {
    $schema: "http://json-schema.org/draft-04/hyper-schema#",
    links: []
};

var validator = new ZSchema();

validator.validateSchema(schema, function (err, report) {
    console.log(report);
});

gives

{ valid: true,
  errors: [],
  warnings: [ { message: 'Unknown key "links" found in schema.', path: '#/' } ] }

Am I right, that for now schemas are not validated against schema specified by URI in $schema key?

work on/with z-schema

I am working on a factory-girl type thing based on json/schema with your library.

Currently I am keeping inin a branch of your z-schema library

https://github.com/leapmotion/z-schema/tree/factory

which also features class files. To do so I have added a method or two to your library and exposed some of its internal componentry.

If you feel this is better put as a seperate (factory) branch I can spin it off, but I'd still need to expose the schema digestion elements as thier own thing.

Can we talk?

Dave Edelhart
Leapmotion

Validation for optional objects

First of all, thank you for a great library. I've found it really useful and its 'options' features is the one which I could not find in other libraries.

I was working with different schema validations for a project. Let's say, my whole JSON body is empty and the schema defines all the fields are optional.

  1. Is there a way to define that even though all the fields are optional, at least one (any of it) should be present in the body and the body should not be empty?
  2. If my JSON body has two fields A and B and the schema defines A and B as optional. Is there a way to define that if A is present, then, B is required?

It may not be a bug, but I could find the documentation supporting such features.

Thank you for your time.

Neeraj

Support for meta data keywords and custom meta data keywords

It would be really great if it was easier to do the following things with Z-Schema

  1. Actually fill in default values into a json instance using the validator.
    This is something which is a real pain especially because of javascript lack of strict type checking. It would be great to be able to ignore keys and just have the validator fill in the default values instead of doing it in a separate piece of code.
  2. Add custom meta data keywords for additional data transformations
    I believe filling in default values would be considered as a meta data operation applied to the json instance before actually performing the validation. Making this operation customizable would be a real time saver for many common scenarios.

The case for a customizable meta data value would be scenario where you may have to perform additional processing on the data before or after validation besides just putting a default value.

For example if we wish to sanitize html which is submitted to the server as a json request. I could simply implement a meta data boolean keyword called sanitize which would then sanitize the input before validating it.

It could also be used for perhaps converting date-time strings to Date or serialized mongoDB objectIDs to ObjectID instances.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.