Git Product home page Git Product logo

is-my-json-valid's Introduction

is-my-json-valid

A JSONSchema validator that uses code generation to be extremely fast.

It passes the entire JSONSchema v4 test suite except for remoteRefs and maxLength/minLength when using unicode surrogate pairs.

build status

Installation

npm install --save is-my-json-valid

Usage

Simply pass a schema to compile it

var validator = require('is-my-json-valid')

var validate = validator({
  required: true,
  type: 'object',
  properties: {
    hello: {
      required: true,
      type: 'string'
    }
  }
})

console.log('should be valid', validate({hello: 'world'}))
console.log('should not be valid', validate({}))

// get the last list of errors by checking validate.errors
// the following will print [{field: 'data.hello', message: 'is required'}]
console.log(validate.errors)

You can also pass the schema as a string

var validate = validator('{"type": ... }')

Optionally you can use the require submodule to load a schema from __dirname

var validator = require('is-my-json-valid/require')
var validate = validator('my-schema.json')

Custom formats

is-my-json-valid supports the formats specified in JSON schema v4 (such as date-time). If you want to add your own custom formats pass them as the formats options to the validator

var validate = validator({
  type: 'string',
  required: true,
  format: 'only-a'
}, {
  formats: {
    'only-a': /^a+$/
  }
})

console.log(validate('aa')) // true
console.log(validate('ab')) // false

External schemas

You can pass in external schemas that you reference using the $ref attribute as the schemas option

var ext = {
  required: true,
  type: 'string'
}

var schema = {
  $ref: '#ext' // references another schema called ext
}

// pass the external schemas as an option
var validate = validator(schema, {schemas: {ext: ext}})

validate('hello') // returns true
validate(42) // return false

Filtering away additional properties

is-my-json-valid supports filtering away properties not in the schema

var filter = validator.filter({
  required: true,
  type: 'object',
  properties: {
    hello: {type: 'string', required: true}
  },
  additionalProperties: false
})

var doc = {hello: 'world', notInSchema: true}
console.log(filter(doc)) // {hello: 'world'}

Verbose mode shows more information about the source of the error

When the verbose options is set to true, is-my-json-valid also outputs:

  • value: The data value that caused the error
  • schemaPath: an array of keys indicating which sub-schema failed
var schema = {
  required: true,
  type: 'object',
  properties: {
    hello: {
      required: true,
      type: 'string'
    }
  }
}
var validate = validator(schema, {
  verbose: true
})

validate({hello: 100});
console.log(validate.errors)
// [ { field: 'data.hello',
//     message: 'is the wrong type',
//     value: 100,
//     type: 'string',
//     schemaPath: [ 'properties', 'hello' ] } ]

Many popular libraries make it easy to retrieve the failing rule with the schemaPath:

var schemaPath = validate.errors[0].schemaPath
var R = require('ramda')

console.log( 'All evaluate to the same thing: ', R.equals(
  schema.properties.hello,
  { required: true, type: 'string' },
  R.path(schemaPath, schema),
  require('lodash').get(schema, schemaPath),
  require('jsonpointer').get(schema, [""].concat(schemaPath))
))
// All evaluate to the same thing: true

Greedy mode tries to validate as much as possible

By default is-my-json-valid bails on first validation error but when greedy is set to true it tries to validate as much as possible:

var validate = validator({
  type: 'object',
  properties: {
    x: {
      type: 'number'
    }
  },
  required: ['x', 'y']
}, {
  greedy: true
});

validate({x: 'string'});
console.log(validate.errors) // [{field: 'data.y', message: 'is required'},
                             //  {field: 'data.x', message: 'is the wrong type'}]

Error messages

Here is a list of possible message values for errors:

  • is required
  • is the wrong type
  • has additional items
  • must be FORMAT format (FORMAT is the format property from the schema)
  • must be unique
  • must be an enum value
  • dependencies not set
  • has additional properties
  • referenced schema does not match
  • negative schema matches
  • pattern mismatch
  • no schemas match
  • no (or more than one) schemas match
  • has a remainder
  • has more properties than allowed
  • has less properties than allowed
  • has more items than allowed
  • has less items than allowed
  • has longer length than allowed
  • has less length than allowed
  • is less than minimum
  • is more than maximum

Performance

is-my-json-valid uses code generation to turn your JSON schema into basic javascript code that is easily optimizeable by v8.

At the time of writing, is-my-json-valid is the fastest validator when running

If you know any other relevant benchmarks open a PR and I'll add them.

TypeScript support

This library ships with TypeScript typings. They are still early on and not perfect at the moment, but should hopefully handle the most common cases. If you find anything that doesn't work, please open an issue and we'll try to solve it.

The typings are using unknown and thus require TypeScript 3.0 or later.

Here is a quick sample of usage together with express:

import createError = require('http-errors')
import createValidator = require('is-my-json-valid')
import { Request, Response, NextFunction } from 'express'

const personValidator = createValidator({
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'number' },
  },
  required: [
    'name'
  ]
})

export function post (req: Request, res: Response, next: NextFunction) {
  // Here req.body is typed as: any

  if (!personValidator(req.body)) {
    throw createError(400, { errors: personValidator.errors })
  }

  // Here req.body is typed as: { name: string, age: number | undefined }
}

As you can see, the typings for is-my-json-valid will contruct an interface from the schema passed in. This allows you to work with your incoming json body in a type safe way.

License

MIT

is-my-json-valid's People

Contributors

ahdinosaur avatar andreypopp avatar billinghamj avatar bobthekingofegypt avatar cameojokes avatar chalker avatar chrahunt avatar creynders avatar danieljuhl avatar electricg avatar emilbayes avatar hville avatar jackmoore avatar linusu avatar mafintosh avatar mar-v-in avatar nswbmw avatar rangermauve avatar rgbboy avatar shalevshalit avatar thokari avatar watson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

is-my-json-valid's Issues

Include name of the validation rule in errors?

I was thinking of using this to validate data and then show friendly errors to the user, so I'd have to map the errors from is-my-json-valid onto some user-friendly messages. I could do this if each errors object contained the name of the rule in question ("minLength", "required", etc) Is that something that could be added to the "verbose" mode?

EDIT added example:

// validator.errors
{ field: 'data.test',
    message: 'has less length than allowed',
    value: 'hello',
    rule: 'minLength' },
{ field: 'data.requiredProp',
    message: 'is required',
    value: undefined,
    rule: 'required' } ]

Wrong result of a validation

var _schema = {
  "$schema": "http://json-schema.org/draft-04/schema#",
  "id": "http://jsonschema.net",
  "type": "array",
  "items": [
    {
      "id": "http://jsonschema.net/0",
      "type": "object",
      "properties": {
        "_id": {
          "id": "http://jsonschema.net/0/_id",
          "type": "number"
        },
        "index": {
          "id": "http://jsonschema.net/0/index",
          "type": "integer"
        },
        "guid": {
          "id": "http://jsonschema.net/0/guid",
          "type": "number"
        },
        "isActive": {
          "id": "http://jsonschema.net/0/isActive",
          "type": "boolean"
        },
        "balance": {
          "id": "http://jsonschema.net/0/balance",
          "type": "string"
        },
        "picture": {
          "id": "http://jsonschema.net/0/picture",
          "type": "string"
        },
        "age": {
          "id": "http://jsonschema.net/0/age",
          "type": "integer"
        },
        "eyeColor": {
          "id": "http://jsonschema.net/0/eyeColor",
          "type": "string"
        },
        "name": {
          "id": "http://jsonschema.net/0/name",
          "type": "string"
        },
        "gender": {
          "id": "http://jsonschema.net/0/gender",
          "type": "string"
        },
        "company": {
          "id": "http://jsonschema.net/0/company",
          "type": "string"
        },
        "email": {
          "id": "http://jsonschema.net/0/email",
          "type": "string"
        },
        "phone": {
          "id": "http://jsonschema.net/0/phone",
          "type": "string"
        },
        "address": {
          "id": "http://jsonschema.net/0/address",
          "type": "string"
        },
        "about": {
          "id": "http://jsonschema.net/0/about",
          "type": "string"
        },
        "registered": {
          "id": "http://jsonschema.net/0/registered",
          "type": "string"
        },
        "latitude": {
          "id": "http://jsonschema.net/0/latitude",
          "type": "number"
        },
        "longitude": {
          "id": "http://jsonschema.net/0/longitude",
          "type": "number"
        },
        "tags": {
          "id": "http://jsonschema.net/0/tags",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/0/tags/0",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/0/tags/1",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/0/tags/2",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/0/tags/3",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/0/tags/4",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/0/tags/5",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/0/tags/6",
              "type": "string"
            }
          ]
        },
        "friends": {
          "id": "http://jsonschema.net/0/friends",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/0/friends/0",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/0/friends/0/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/0/friends/0/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/0/friends/1",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/0/friends/1/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/0/friends/1/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/0/friends/2",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/0/friends/2/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/0/friends/2/name",
                  "type": "string"
                }
              }
            }
          ]
        },
        "greeting": {
          "id": "http://jsonschema.net/0/greeting",
          "type": "string"
        },
        "favoriteFruit": {
          "id": "http://jsonschema.net/0/favoriteFruit",
          "type": "string"
        }
      },
      "required": [
        "_id",
        "index",
        "guid",
        "isActive",
        "balance",
        "picture",
        "age",
        "eyeColor",
        "name",
        "gender",
        "company",
        "email",
        "phone",
        "address",
        "about",
        "registered",
        "latitude",
        "longitude",
        "tags",
        "friends",
        "greeting",
        "favoriteFruit"
      ]
    },
    {
      "id": "http://jsonschema.net/1",
      "type": "object",
      "properties": {
        "_id": {
          "id": "http://jsonschema.net/1/_id",
          "type": "string"
        },
        "index": {
          "id": "http://jsonschema.net/1/index",
          "type": "integer"
        },
        "guid": {
          "id": "http://jsonschema.net/1/guid",
          "type": "string"
        },
        "isActive": {
          "id": "http://jsonschema.net/1/isActive",
          "type": "boolean"
        },
        "balance": {
          "id": "http://jsonschema.net/1/balance",
          "type": "string"
        },
        "picture": {
          "id": "http://jsonschema.net/1/picture",
          "type": "string"
        },
        "age": {
          "id": "http://jsonschema.net/1/age",
          "type": "integer"
        },
        "eyeColor": {
          "id": "http://jsonschema.net/1/eyeColor",
          "type": "string"
        },
        "name": {
          "id": "http://jsonschema.net/1/name",
          "type": "string"
        },
        "gender": {
          "id": "http://jsonschema.net/1/gender",
          "type": "string"
        },
        "company": {
          "id": "http://jsonschema.net/1/company",
          "type": "string"
        },
        "email": {
          "id": "http://jsonschema.net/1/email",
          "type": "string"
        },
        "phone": {
          "id": "http://jsonschema.net/1/phone",
          "type": "string"
        },
        "address": {
          "id": "http://jsonschema.net/1/address",
          "type": "string"
        },
        "about": {
          "id": "http://jsonschema.net/1/about",
          "type": "string"
        },
        "registered": {
          "id": "http://jsonschema.net/1/registered",
          "type": "string"
        },
        "latitude": {
          "id": "http://jsonschema.net/1/latitude",
          "type": "number"
        },
        "longitude": {
          "id": "http://jsonschema.net/1/longitude",
          "type": "number"
        },
        "tags": {
          "id": "http://jsonschema.net/1/tags",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/1/tags/0",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/1/tags/1",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/1/tags/2",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/1/tags/3",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/1/tags/4",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/1/tags/5",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/1/tags/6",
              "type": "string"
            }
          ]
        },
        "friends": {
          "id": "http://jsonschema.net/1/friends",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/1/friends/0",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/1/friends/0/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/1/friends/0/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/1/friends/1",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/1/friends/1/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/1/friends/1/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/1/friends/2",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/1/friends/2/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/1/friends/2/name",
                  "type": "string"
                }
              }
            }
          ]
        },
        "greeting": {
          "id": "http://jsonschema.net/1/greeting",
          "type": "string"
        },
        "favoriteFruit": {
          "id": "http://jsonschema.net/1/favoriteFruit",
          "type": "string"
        }
      }
    },
    {
      "id": "http://jsonschema.net/2",
      "type": "object",
      "properties": {
        "_id": {
          "id": "http://jsonschema.net/2/_id",
          "type": "string"
        },
        "index": {
          "id": "http://jsonschema.net/2/index",
          "type": "integer"
        },
        "guid": {
          "id": "http://jsonschema.net/2/guid",
          "type": "string"
        },
        "isActive": {
          "id": "http://jsonschema.net/2/isActive",
          "type": "boolean"
        },
        "balance": {
          "id": "http://jsonschema.net/2/balance",
          "type": "string"
        },
        "picture": {
          "id": "http://jsonschema.net/2/picture",
          "type": "string"
        },
        "age": {
          "id": "http://jsonschema.net/2/age",
          "type": "integer"
        },
        "eyeColor": {
          "id": "http://jsonschema.net/2/eyeColor",
          "type": "string"
        },
        "name": {
          "id": "http://jsonschema.net/2/name",
          "type": "string"
        },
        "gender": {
          "id": "http://jsonschema.net/2/gender",
          "type": "string"
        },
        "company": {
          "id": "http://jsonschema.net/2/company",
          "type": "string"
        },
        "email": {
          "id": "http://jsonschema.net/2/email",
          "type": "string"
        },
        "phone": {
          "id": "http://jsonschema.net/2/phone",
          "type": "string"
        },
        "address": {
          "id": "http://jsonschema.net/2/address",
          "type": "string"
        },
        "about": {
          "id": "http://jsonschema.net/2/about",
          "type": "string"
        },
        "registered": {
          "id": "http://jsonschema.net/2/registered",
          "type": "string"
        },
        "latitude": {
          "id": "http://jsonschema.net/2/latitude",
          "type": "number"
        },
        "longitude": {
          "id": "http://jsonschema.net/2/longitude",
          "type": "number"
        },
        "tags": {
          "id": "http://jsonschema.net/2/tags",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/2/tags/0",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/2/tags/1",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/2/tags/2",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/2/tags/3",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/2/tags/4",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/2/tags/5",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/2/tags/6",
              "type": "string"
            }
          ]
        },
        "friends": {
          "id": "http://jsonschema.net/2/friends",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/2/friends/0",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/2/friends/0/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/2/friends/0/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/2/friends/1",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/2/friends/1/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/2/friends/1/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/2/friends/2",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/2/friends/2/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/2/friends/2/name",
                  "type": "string"
                }
              }
            }
          ]
        },
        "greeting": {
          "id": "http://jsonschema.net/2/greeting",
          "type": "string"
        },
        "favoriteFruit": {
          "id": "http://jsonschema.net/2/favoriteFruit",
          "type": "string"
        }
      }
    },
    {
      "id": "http://jsonschema.net/3",
      "type": "object",
      "properties": {
        "_id": {
          "id": "http://jsonschema.net/3/_id",
          "type": "string"
        },
        "index": {
          "id": "http://jsonschema.net/3/index",
          "type": "integer"
        },
        "guid": {
          "id": "http://jsonschema.net/3/guid",
          "type": "string"
        },
        "isActive": {
          "id": "http://jsonschema.net/3/isActive",
          "type": "boolean"
        },
        "balance": {
          "id": "http://jsonschema.net/3/balance",
          "type": "string"
        },
        "picture": {
          "id": "http://jsonschema.net/3/picture",
          "type": "string"
        },
        "age": {
          "id": "http://jsonschema.net/3/age",
          "type": "integer"
        },
        "eyeColor": {
          "id": "http://jsonschema.net/3/eyeColor",
          "type": "string"
        },
        "name": {
          "id": "http://jsonschema.net/3/name",
          "type": "string"
        },
        "gender": {
          "id": "http://jsonschema.net/3/gender",
          "type": "string"
        },
        "company": {
          "id": "http://jsonschema.net/3/company",
          "type": "string"
        },
        "email": {
          "id": "http://jsonschema.net/3/email",
          "type": "string"
        },
        "phone": {
          "id": "http://jsonschema.net/3/phone",
          "type": "string"
        },
        "address": {
          "id": "http://jsonschema.net/3/address",
          "type": "string"
        },
        "about": {
          "id": "http://jsonschema.net/3/about",
          "type": "string"
        },
        "registered": {
          "id": "http://jsonschema.net/3/registered",
          "type": "string"
        },
        "latitude": {
          "id": "http://jsonschema.net/3/latitude",
          "type": "number"
        },
        "longitude": {
          "id": "http://jsonschema.net/3/longitude",
          "type": "number"
        },
        "tags": {
          "id": "http://jsonschema.net/3/tags",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/3/tags/0",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/3/tags/1",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/3/tags/2",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/3/tags/3",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/3/tags/4",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/3/tags/5",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/3/tags/6",
              "type": "string"
            }
          ]
        },
        "friends": {
          "id": "http://jsonschema.net/3/friends",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/3/friends/0",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/3/friends/0/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/3/friends/0/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/3/friends/1",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/3/friends/1/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/3/friends/1/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/3/friends/2",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/3/friends/2/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/3/friends/2/name",
                  "type": "string"
                }
              }
            }
          ]
        },
        "greeting": {
          "id": "http://jsonschema.net/3/greeting",
          "type": "string"
        },
        "favoriteFruit": {
          "id": "http://jsonschema.net/3/favoriteFruit",
          "type": "string"
        }
      }
    },
    {
      "id": "http://jsonschema.net/4",
      "type": "object",
      "properties": {
        "_id": {
          "id": "http://jsonschema.net/4/_id",
          "type": "string"
        },
        "index": {
          "id": "http://jsonschema.net/4/index",
          "type": "integer"
        },
        "guid": {
          "id": "http://jsonschema.net/4/guid",
          "type": "string"
        },
        "isActive": {
          "id": "http://jsonschema.net/4/isActive",
          "type": "boolean"
        },
        "balance": {
          "id": "http://jsonschema.net/4/balance",
          "type": "string"
        },
        "picture": {
          "id": "http://jsonschema.net/4/picture",
          "type": "string"
        },
        "age": {
          "id": "http://jsonschema.net/4/age",
          "type": "integer"
        },
        "eyeColor": {
          "id": "http://jsonschema.net/4/eyeColor",
          "type": "string"
        },
        "name": {
          "id": "http://jsonschema.net/4/name",
          "type": "string"
        },
        "gender": {
          "id": "http://jsonschema.net/4/gender",
          "type": "string"
        },
        "company": {
          "id": "http://jsonschema.net/4/company",
          "type": "string"
        },
        "email": {
          "id": "http://jsonschema.net/4/email",
          "type": "string"
        },
        "phone": {
          "id": "http://jsonschema.net/4/phone",
          "type": "string"
        },
        "address": {
          "id": "http://jsonschema.net/4/address",
          "type": "string"
        },
        "about": {
          "id": "http://jsonschema.net/4/about",
          "type": "string"
        },
        "registered": {
          "id": "http://jsonschema.net/4/registered",
          "type": "string"
        },
        "latitude": {
          "id": "http://jsonschema.net/4/latitude",
          "type": "number"
        },
        "longitude": {
          "id": "http://jsonschema.net/4/longitude",
          "type": "number"
        },
        "tags": {
          "id": "http://jsonschema.net/4/tags",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/4/tags/0",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/4/tags/1",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/4/tags/2",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/4/tags/3",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/4/tags/4",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/4/tags/5",
              "type": "string"
            },
            {
              "id": "http://jsonschema.net/4/tags/6",
              "type": "string"
            }
          ]
        },
        "friends": {
          "id": "http://jsonschema.net/4/friends",
          "type": "array",
          "items": [
            {
              "id": "http://jsonschema.net/4/friends/0",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/4/friends/0/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/4/friends/0/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/4/friends/1",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/4/friends/1/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/4/friends/1/name",
                  "type": "string"
                }
              }
            },
            {
              "id": "http://jsonschema.net/4/friends/2",
              "type": "object",
              "properties": {
                "id": {
                  "id": "http://jsonschema.net/4/friends/2/id",
                  "type": "integer"
                },
                "name": {
                  "id": "http://jsonschema.net/4/friends/2/name",
                  "type": "string"
                }
              }
            }
          ]
        },
        "greeting": {
          "id": "http://jsonschema.net/4/greeting",
          "type": "string"
        },
        "favoriteFruit": {
          "id": "http://jsonschema.net/4/favoriteFruit",
          "type": "string"
        }
      }
    }
  ],
  "required": [
    "0",
    "1",
    "2",
    "3",
    "4"
  ]
};
var obj = [
  {
    "_id": "556560b766605c41d66d5910",
    "index": 0,
    "guid": "b0057de2-b2b9-4f5e-8a10-3259e54ac5ae",
    "isActive": true,
    "balance": "$3,798.63",
    "picture": "http://placehold.it/32x32",
    "age": 40,
    "eyeColor": "blue",
    "name": "Shawn Evans",
    "gender": "female",
    "company": "FOSSIEL",
    "email": "[email protected]",
    "phone": "+1 (956) 479-2930",
    "address": "879 Meserole Avenue, Norvelt, Indiana, 428",
    "about": "Cillum qui dolor quis sunt do aliquip aliqua pariatur ut laborum. Anim sit dolor tempor fugiat mollit nostrud veniam ad velit elit. Ea commodo ad incididunt voluptate.\r\n",
    "registered": "2014-04-20T14:33:16 -04:00",
    "latitude": -40.01082,
    "longitude": -118.957523,
    "tags": [
      "consequat",
      "ex",
      "non",
      "irure",
      "id",
      "sint",
      "eu"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Keisha Duncan"
      },
      {
        "id": 1,
        "name": "Blanca Cantu"
      },
      {
        "id": 2,
        "name": "Deidre Cotton"
      }
    ],
    "greeting": "Hello, Shawn Evans! You have 1 unread messages.",
    "favoriteFruit": "apple"
  },
  {
    "_id": "556560b74f4b9e71e73d7856",
    "index": 1,
    "guid": "92c770b3-80b8-4bdc-aad4-9a2330bb0a23",
    "isActive": true,
    "balance": "$1,315.39",
    "picture": "http://placehold.it/32x32",
    "age": 29,
    "eyeColor": "brown",
    "name": "Lucas Pacheco",
    "gender": "male",
    "company": "MOTOVATE",
    "email": "[email protected]",
    "phone": "+1 (988) 541-2454",
    "address": "589 Gunther Place, Carrsville, Washington, 520",
    "about": "Deserunt cillum magna ut irure nostrud dolor sunt excepteur anim enim. Qui dolore fugiat nulla velit velit fugiat proident nostrud nulla exercitation non. Tempor tempor et consequat consequat aute eiusmod commodo veniam ad veniam laborum.\r\n",
    "registered": "2015-04-24T03:13:02 -04:00",
    "latitude": -45.336031,
    "longitude": 150.45798,
    "tags": [
      "id",
      "laboris",
      "ea",
      "officia",
      "laborum",
      "minim",
      "labore"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Jackson Charles"
      },
      {
        "id": 1,
        "name": "Burt Cline"
      },
      {
        "id": 2,
        "name": "Weiss Randall"
      }
    ],
    "greeting": "Hello, Lucas Pacheco! You have 10 unread messages.",
    "favoriteFruit": "strawberry"
  },
  {
    "_id": "556560b7a46b9075e0196ceb",
    "index": 2,
    "guid": "ee7bd878-7759-4805-93ad-dff5358c9127",
    "isActive": true,
    "balance": "$2,162.78",
    "picture": "http://placehold.it/32x32",
    "age": 28,
    "eyeColor": "green",
    "name": "Haynes Mccarthy",
    "gender": "male",
    "company": "DUOFLEX",
    "email": "[email protected]",
    "phone": "+1 (982) 465-2986",
    "address": "964 Amity Street, Clinton, Montana, 3904",
    "about": "Nostrud excepteur exercitation aliquip deserunt pariatur enim amet aute qui. Aliquip est dolore dolor deserunt irure laborum cillum dolor. Cillum id est aliquip aliquip sunt anim tempor officia est. Amet Lorem consectetur sint nulla incididunt est occaecat. Do aute enim est laboris laboris cillum culpa ea. Nulla velit id labore aliquip voluptate ex.\r\n",
    "registered": "2014-07-31T00:55:13 -04:00",
    "latitude": -75.735289,
    "longitude": 104.668396,
    "tags": [
      "anim",
      "do",
      "ea",
      "reprehenderit",
      "laboris",
      "commodo",
      "ea"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Bates Mayo"
      },
      {
        "id": 1,
        "name": "Koch Cardenas"
      },
      {
        "id": 2,
        "name": "Harrison Bishop"
      }
    ],
    "greeting": "Hello, Haynes Mccarthy! You have 7 unread messages.",
    "favoriteFruit": "apple"
  },
  {
    "_id": "556560b75909befce91e6e1e",
    "index": 3,
    "guid": "c6606f4c-c424-4614-9ccf-eb24012f6469",
    "isActive": true,
    "balance": "$3,982.88",
    "picture": "http://placehold.it/32x32",
    "age": 21,
    "eyeColor": "brown",
    "name": "Stephens Mercer",
    "gender": "male",
    "company": "ZOID",
    "email": "[email protected]",
    "phone": "+1 (854) 545-3206",
    "address": "332 Autumn Avenue, Makena, New Mexico, 2363",
    "about": "Fugiat reprehenderit consectetur ullamco deserunt. Mollit amet adipisicing sunt voluptate mollit elit non Lorem ut excepteur exercitation minim magna. Esse consectetur adipisicing magna aliqua exercitation anim quis officia et commodo.\r\n",
    "registered": "2014-01-20T15:13:25 -04:00",
    "latitude": -48.455294,
    "longitude": -129.759485,
    "tags": [
      "dolore",
      "id",
      "cupidatat",
      "qui",
      "deserunt",
      "ea",
      "pariatur"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Bridgette Craig"
      },
      {
        "id": 1,
        "name": "Maryellen Saunders"
      },
      {
        "id": 2,
        "name": "Mclaughlin Oneal"
      }
    ],
    "greeting": "Hello, Stephens Mercer! You have 4 unread messages.",
    "favoriteFruit": "apple"
  },
  {
    "_id": "556560b7154ca98f4e1dec03",
    "index": 4,
    "guid": "161c6649-9dc8-4e19-8f61-a99f9ffa0543",
    "isActive": true,
    "balance": "$2,613.57",
    "picture": "http://placehold.it/32x32",
    "age": 30,
    "eyeColor": "green",
    "name": "Rosemarie Levy",
    "gender": "female",
    "company": "NORSUL",
    "email": "[email protected]",
    "phone": "+1 (837) 545-2870",
    "address": "803 Cumberland Street, Loveland, Colorado, 8884",
    "about": "Sit anim est non elit aliquip Lorem enim mollit id exercitation culpa quis. Do irure dolor laborum et consequat ullamco. Quis culpa fugiat do occaecat adipisicing ipsum labore mollit. Ad cillum id voluptate consectetur incididunt dolore non laboris. Dolor exercitation ad exercitation et.\r\n",
    "registered": "2014-11-21T22:37:15 -04:00",
    "latitude": 29.446521,
    "longitude": 69.509939,
    "tags": [
      "deserunt",
      "reprehenderit",
      "qui",
      "tempor",
      "est",
      "enim",
      "non"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Cathleen Griffin"
      },
      {
        "id": 1,
        "name": "Beulah Hester"
      },
      {
        "id": 2,
        "name": "Staci Carney"
      }
    ],
    "greeting": "Hello, Rosemarie Levy! You have 10 unread messages.",
    "favoriteFruit": "strawberry"
  }
];
var j = require('is-my-json-valid');
var validate = j(_schema, { copy:false });
var res = validate(obj);
console.log(res);

As you can see in the schema the property "guid" must be a number, but in the object this property is a string. The result of validation is TRUE. That's wrong!

An another example:
schema = {
type : "number",
multipleOf : 0.0001
}
object = 1;
The result is FALSE, but must be TRUE

Feature request: Make it easy to add schema extensions

We would like to add som schema extensions.
For example if a property has maxDecimals:2, we would like to verify that the number has at most two decimal digits (currency). We would also like to add special handlers for when the format is set to date or date-time.
The module themis. Has a way or registering special formats that looks nice (It also has a way of registering custom validators like the maxDecimals):

Themis.registerFormat('username', function (str) {
  return /^[a-zA-Z0-9_\.-]+$/.test(str);
});

option 'greedy' doesn't seem to work

Schema (I was trying to make it deeper to see the difference)

{ id: 'schema'
  type: 'object',
  properties:
  { obj:
    { type: 'object',
      properties:
      { s: { type: 'string', pattern: '^valid$' },
        n: { type: 'number' } } },
  n: { type: 'number' } } }

json

{ obj: { s: 'invalid', n: 'invalid1' }, n: 'invalid2' }

returns 3 errors regardless of the greedy option:

[ { field: 'data.obj.s', message: 'pattern mismatch' },
  { field: 'data.obj.n', message: 'is the wrong type' },
  { field: 'data.n', message: 'is the wrong type' } ]

flat $ref

I was working through the example underneath Tying this all together. I was wondering if I could do something like below:

var schema = {
  "$schema": "http://json-schema.org/draft-04/schema#",

  "definitions": {
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city":           { "type": "string" },
        "state":          { "type": "string" }
      },
      "required": ["street_address", "city", "state"]
    }
  },

  "type": "object",

        "properties": {
          "$ref": "#/definitions/address",
          "type": { "enum": [ "residential", "business" ] },
          "required": ["type"]
        }
}

var json2 = {
    street_address: 1,
    "city": "Washington",
    "type": "business"
}

var validate = validator(schema)
console.log(json2)
console.log('should be valid', validate(json2))
console.log(validate.errors)

My expectation is that it should be an error since street_address is 1 and not a string. I expect that it will also error since state isn't supplied.

Is this by design in the json-schema spec or is it a bug?

Thanks for your time.

Remote external references

What is the motivation behind not resolving remote external references? See here.

This prevents using complex schemas which reference external resources out-of-the-box (i.e., without having to preprocess a schema with find-and-replace). Based on the JSON schema specification, remote references are allowed.

From the looks of things, jsonpointer follows the IETF specification. But the JSON schema specification suggests that remote resources are permitted.

Any insight into the design decision?

This is related to #66.

no (or more than one) schemas match - not detailed enough

Given the following schema:

{
        id:"/api/accounts/register",
        additionalProperties: false,
        oneOf: [ { $ref:"#/definitions/social"}, { $ref:"#/definitions/site"} ],

        definitions: {
            social: {
                additionalProperties: false,
                required: true,
                type: 'object',
                properties: {
                    provider: { enum: [ "facebook" ], required:true }
                }
            },
            site: {
                additionalProperties: false,
                required: true,
                type: 'object',
                properties: {
                    username: { type: "string", required:true },
                    password: { type: "string", required:true },

                    firstname: { type: "string" },
                    lastname: { type: "string" },
                    email: { type: "string" },
                    isSubscribed: { type: "boolean" }
                }
            }
        }

    }

i get the following validation error:

[
      {
        "field": "data",
        "message": "no (or more than one) schemas match",
        "value": {

        }
      }
    ]

i would expect to get the following or something similar which is much more useful:

[
      {
        "field": "data",
        "message": "no (or more than one) schemas match",
        "value": {

        }
      },

     {
        "field": "data",
        "type": "oneOf",
        "message": "one of",
        "value": [
             { "message": "is required", "field": ["username","password"]  },
             { "message": "is required", "field": ["provider"]  },
        ]
     }
    ]

this will allow me to show the user that either ( username and password ) or (provider) are missing.

Type coercion (or data cleaning)

Is there a way to coerce a given property?
I'm doing a custom validation the following way:

var schema = {
  type: 'object',
  properties: {
    _id: {
      // type: ['string', 'mongoId'],
      format: 'mongoId'
    }
  }
};

var mongoId = function(_id) {
  // check if it's a string or a mongoId and validate it
};

var validate = validator(schema, {formats: {mongoId: mongoId}});

Now, I want to auto coerce the _id to an OjectID (mongo id type) whenever a string is received.
I'm thinking something along the lines of:

var schema = {
  type: 'object',
  properties: {
    _id: {
      // type: ['string', 'mongoId'],
      format: 'mongoId',
      coerce: 'objectId',
    }
  }
};

var objectId = function(_id) {
  // coerce the _id to an objectId
  return coercedValue;
};

var validate = validator(schema, {coercers: {objectId: objectId}});

validate({_id: 'qwerty123'});
console.info(validate.data);  // {_id: ObjectID(qwerty123)}

The coercing would take place after all the other validations. My use case is specific to mongo but it'd be an useful feature for other type conversions.

Loading a schema in is-my-json-valid has side effects

The schema:

{
                "items": [
                        {}
                ],
                "additionalItems": {
                        "type": "integer"
                }
}

gets turned into

 {
                "items": [
                        {}
                ],
                "additionalItems": {
                        "type": "integer"
                },
                "properties": {
                        "0": {}
                },
                "type": "array",
                "tuple": true
}

I don't think loading a schema should have side-effects on the original schema.

Multiple validation in the same validade(...)

Hi guys! Great module, specially on how the errors object is returned!

So, is there anyway to validate all rules at the same time, including all the rules for the same property? As I can see, is-my-json-valid is making validation in batches.

Edge case: minItems isn't honored when also using required

When given the following schema

{
  "type": ["array", "object" ],
  "items": {
    "type": "string"
  },
  "minItems": 1,
  "properties": {
    "foo": {
      "type": "number"
    }
  },
  "required": [ "foo" ]
}

an empty array shouldn't validate, since minItems is 1. But it does:

> var validator = require('is-my-json-valid')
undefined
> var validate = validator({
...   "type": ["array", "object" ],
...   "items": {
.....     "type": "string"
.....   },
...   "minItems": 1,
...   "properties": {
.....     "foo": {
.......       "type": "number"
.......     }
.....   },
...   "required": [ "foo" ]
... });
undefined
> console.log(validate([]))
true
undefined
> console.log(validate.errors)
null
undefined

add a sub of a sub Schema

Hi,

I wanna add a sub of a sub schema :

for example :

var subOfsubSchema = {
description: "JSON schema ",
type: "object",
additionalProperties: false,
properties: {
mypropriety: {type: "string", required: true},
}
};

var subSchema = {
description: "JSON schema ",
type: "object",
additionalProperties: false,
properties: {
name: {type: "string", maxLength: 256, required: true},
myreference: {"$ref": "#subOfsubSchema", required: true}
}
};

schema = {
description: "JSON schema ",

type: "object",
additionalProperties: false,
properties: {

  propriete1 : { required: true, type: "string"},

  propriete2 : { $ref: '#subSchema', required: true},

}

}

So if i wanna add a sub schema we do that :

validator = validator(schema, {schemas: { subSchema: subSchema}});

So how can i add subOfsubSchema to subSchema

Thanks

how can i prevent the repeate of items

Hi,
I set a parameter of items, and i wanna the items be unique,
I do that but it doesn't work
my_parameter: {
type: "array", required: false, minItems: 1, maxItems: 5, uniqueItems: "", items: {
type: "string", format: "uri"
}

Any one can help me,

Thanks

Use json-pointer instead of dot-joined paths for the `field` property of errors

Right now the an error message looks something like this:

[
    { field: 'data.y', message: 'is required'},
    { field: 'data.x', message: 'is the wrong type'}
]

This makes it easy to work with until one of the field names contains a period. Using json-pointer would solve this. It's extremely fast to build and parse, is a well known standard, and is already part of json-schema.

// the object
{
    'domains': {
        'www.google.com': {
            'company_name': 22
        }
    }
}

// the error
[
    { field: 'domains.www.google.com.company_name', message: 'is the wrong type'}
]


// using json-pointer
[
    { field: '/domains/www.google.com/company_name', message: 'is the wrong type'}
]

Nested object validation assumes existence of optional parent nodes

Currently using IMJV to create a schema validator. Ran into a few failing tests which seem to be related to the same issue.

    if (data.x !== undefined) {
        if (!(typeof data.x === "object" && data.x && !Array.isArray(data.x))) {
          errors++
          if (validate.errors === null) validate.errors = []
          validate.errors.push(error35)
        } else {
          if (data.x.y.z === undefined) {
            errors++
            if (validate.errors === null) validate.errors = []
            validate.errors.push(error36)
          } else {
            if (!(typeof data.x.y === "object" && data.x.y && !Array.isArray(data.x.y))) {
              errors++
              if (validate.errors === null) validate.errors = []
              validate.errors.push(error37)
            } else {
              if (data.x.y.z !== undefined) {
                if (!(typeof data.x.y.z === "string")) {
                  errors++
                  if (validate.errors === null) validate.errors = []
                  validate.errors.push(error38)
                } else {
                }
              }
            }
          }
        }
      }
   }

The issue arises when a nested object is an optional property of a parent node. In the above example, x is an optional property of data. The generated validator correctly checks to make sure the x property exists before continuing with validation.

Similarly, y is an optional property of the object x. If y exists, it is also an object having properties; e.g., z. In the above code, after confirming that data.x is an object, the validator proceeds to determine if data.x.y.z exists before having determined that data.x.y exists.

This causes problems. For example, data.x = {} will throw, as you cannot read property z of undefined.

To my knowledge, what should happen is the following:

  1. Check if optional property x exists.
    • If yes, proceed to 2.
  2. Check if data.x is an object.
    • If no, return an error; else proceed to step 3.
  3. Check if optional property y exists.
    • If no, return to step 1 and check for next property; else proceed to step 4.
  4. Check if data.x.y is an object.
    • If no, return an error; else proceed to step 5.
  5. Check if required property z exists.
    • If no, return an error; else proceed to step 6.
  6. Check if data.x.y.z is a string.
    • If no, return an error; else return to step 1 and check for next property.

If so, then the code generation needs to be altered to reflect this sequence.

A related issue arises if we set data.x.y = null. This should fail validation, as data.x.y is not a plain object. What happens, however, is that the validator throws, as you cannot read property z of null.

Please use latest jsonpointer module

Please, use latest jsonpointer module (version 2.0.0).
They have removed require('console') which was a mistake and therefore I am not able to use your module with webpack.

Option to substitute in default values

In JSON schema it's possible to define default values:

{
  type: "object"
  properties: {
    luckyNumber: {
      type: "number",
      default: 3
    }
  }
}

It is technically irrelevant to validation. But it's very useful to have the validator set default values on
the object validated, if they are not provide.

In the example above, validating {} should succeed while returning {luckyNumber: 3}.

Details to Consider

(A) As this is not part of the specification, and it modifies the input object. I would suggest that it is hidden behind an option useDefaults that defaults to false.

(B) Forbid combination of required and default, complain when compiling a schema that has this, if the useDefaults option is true. Example, if luckyNumber was a required property, we should not be allowed to specify a default value when useDefault is true.

(C) In a case with objects, we should probably allow the first default in the tree to define properties. Example:

{
  type: "object"
  properties: {
    luckyNumber: {
      type: "number",
      default: 3
    },
    luckyNumberTwo: {
      type: "number",
      default: 2
    }
  },
  default: {luckyNumber: 1}
}

In this case {} validates and becomes {luckyNumber: 3, luckyNumberTwo:2}.
While undefined validates and becomes {luckyNumber: 1, luckyNumberTwo:2}.
Or maybe this should be forbidden and checked for at compile time, not sure that's possible though.
It's a bit of a complicated scenario.


Is there any interest to do this or accept a patch (I don't have time right now), but open this issue is a start. This feature is very useful in many cases and keeps code and docs closely aligned.

Note: It probably makes sense to mutate the input object when doing this (if possible), if the input object is a value, one could in addition to (mutating it) output the result as validate.value, just like you do with errors.

filter() constructor doesn't seem to show errors.

I have a small validator written as such:

var vState = validator.filter({
  required: true,
  type: 'object',
  properties: {
    state_iso: {
      required: true,
      type: 'string'
    },
    state_name: {
      required: true,
      type: 'string'
    },
    fips_code: {
      required: false,
      type: 'number'
    }
  },
  additionalProperties: false
});

Long story short, if I take off the .filter, it will throw errors if I take off required fields and the like, but also throw errors on fields that need to be stripped. if I put filter on, it seems the validator won't pass, but the errors array is always undefined.
simple route logic right now just to test this is:

console.log(req.body)
  vState(req.body)
  console.log(req.body)
  console.log(vState.errors)
  res.end()

my actual code is commented out

Output the value on error

For now I've made a little function which iterates the errors and add the value from the validated data set, to each error. Wouldn't it be a nice enhancement to is-my-json-valid? Maybe added using a flag when creating the validator, like the newly added filter-flag.

The output I use is:

{
  field: 'data.size',
  message: 'is less than minimum',
  value: 0
}

It makes it faster to investigate the errors in the data set.

Error when reading property of JSON that may be null.

While reviewing the comment here on #22, I came across a bug where we try to read the properties of a possible null value.

This can be recreated with the following on 2.12.0:

var validator = require('is-my-json-valid');

var validate = validator({
  "type": ["null", "object"],
  "properties": {
    "example": { "type": "string" }
  }
});

validate(null);

Browser support

Are there any plans to include browser support in this project? IMJV performs far better than the current JSON Schema validators that also work in the browser (Z-Schema and tv4). Using browserify in combination with

window.imjv = require('./index.js')

worked fine for me, and validating my objects takes 30ms compared to upwards of 3.5s using Z-Schema. I'd hate to think that others are skipping this library and its performance benefits because there isn't a pre-built version for web browsers.

Option to filter away properties not in schema

@mafintosh I talked to you about makeing a filter-my-json module, that filters away propertien not in schema. But the more I think about anyOf, allOf, etc. Plus the bugfixing going on in is-my-json-valid the more I come to the conclusion that filter-my-json would make much more sense as an option to filter in is-my-json-valid
Something like:

var validate = imjv(schema);
validate(doc, { filter:true });

Would you be interested in a pull request that implemented this filter option when validating?

URI schema resolver

Currently, external schemata are ignored. Example:

{ "$ref": "http://example.org/schema/definitions.json#/definitions/uuid" }

I would propose something along the lines of this:

var validate = validator(schema, {
    schemaUriResolver: function(uri, callback) {
         // uri is "http://example.org/schema/definitions.json", excluding the fragment
         http.get(uri, function(res) {
             callback(JSON.parse(res.body));
         });
    }
});

This would obviously require some restructuring of the code, since it is not async-compatible at the moment.

Alternatively, it would be great if we could accept top-level schemata instead of duplicating all sub-schema paths when providing those up-front.

Any thoughts?

Better error messages when oneOf/anyOf doesn't match

Consider this example:

var schema = {
    "type": "object",
    "required": ["foo", "bar"],
    "additionalProperties": false,
    "properties": {
        "foo": {
            "type": "integer"
        },
        "bar": {
            "oneOf": [{
                "type": "object",
                "required": ["id"],
                "additionalProperties": false,
                "properties": {
                    "id": {
                        "type": "integer"
                    }
                }
            }, {
                "type": null,
                "additionalProperties": false
            }]
        }
    }
};

var candidate = {
    "foo": 123,
    "bar": {
        "id": 456
    }
};

Based on the schema the candidate is valid. However, if I change the id to a string value (e.g "456"), I will get this error:

[ { field: 'data.bar',
    message: 'no (or more than one) schemas match' } ]

While the error message is not wrong, it can be more informative by saying which field has issue.
The same thing can apply for missing required fields or having additional properties when it's not allowed.

Browser support?

I really like the API of this library over the other json scheme validation libraries. Just wondering if browser support is going to be considered?

Nested External Schema Reference doesn't work

When using this library, the ref to an external schema just doesn't work, but when using others such as tv4, it works perfectly fine.

The Schema

{
  "type": "object",
  "properties": {
     "body":  "$ref": "#oauth"
  }
}

And the defs schema

{
  "definitions": {
    "oauth": { ... }
  }
}

when doing

validate = validator(schema, { "schemas": defs.definitions }); validate(req);

The error l get is: reference schema does not match

Indicate when referenced schema isn't available

If a schema is being referenced via $ref and that reference cannot be resolved within the schema itself or from one of the schemas passed into the schemas property of the options, this needs to be indicated. A reasonable default would be to throw an error, but it would also be appropriate to indicate this issue at validation-time (as done in #46).

This would help take care of some of the issues referenced in #22.

Junk characters in index.js

index.js

Line 135:
validate('validate.errors.push({field:%s,message:%s,value:%s})', JSON.stringify(formatName(prop || name)), JSON.stringify(msg), value ||ร‚ name)

Line 138:
scope[n] = {field:formatName(prop ||ร‚ name), message:msg}

There is a junk character after || (if will be able to see if switch your browser from "Encoding / Unicode UTF-8" to "Encoding / Windows-1252")

Causing us some issues and should be easy to fix (just delete this character please).

Async API

Hi

How would you feel about adding the option for the validation to happen asynchronous as opposed to synchronous?

It's already fast as-is, but an async API would be amazing as it won't block the running code.

Thanks!

error codes & localization

Please add support for error codes, this will allow better understanding of the errors, and allow us as developers to localize the error messages,
currently errors contains:

  1. field
  2. value
  3. message

we also need:

  1. errorCode

this means that its should be supported in the custom format as well,

Thanks,

support JavaScript plain Date objects as date-time.

Is it possible to support a Date object? Since once I JSON.stringify the date it will be a proper date, but before then I would like to use it as a date object. Maybe when checking if it is date-time if it is not a string try and JSON.stringify then check it?

Is there another way around this?

Recursively filter object

Currently it doesn't seem like nested objects/arrays are supported for the filter functionality. This would be really useful. When I have time I'll try and implement it. But if anyone else gets to it before me that would be great!

Error codes for standard errors

Hi, nice work on this validator and its performance. One thing that keeps me from being able to use it, however, is that there aren't predefined codes for the built in validation errors. It is something that tv4 (the only other one I've used extensively) does well. With error codes I can store the errors and map to messages that make sense within my systems. Perhaps you'd consider this?

Here is the link to how tv4 does errors: https://github.com/geraintluff/tv4/blob/master/source/api.js

Thanks!

Bug in patternProperties

the json should be failed by the schema as 'a' does not match the patternProperties regex. However the json is accepted and no errors are returned

schema:

{
"type": "object",
"properties": {
"fixedKey": {
"type": "object",
"patternProperties": {
"[0-9]*": {}
},
"additionalProperties": false
}
}
}

test json:

{
"fixedKey": {
"1": {},
"a": {}
}
}

patternProperties error field has an extra `]`

Invalid patternProperties result in { field: 'data.*]', message: 'is the wrong type' } (notice the extra ]). It seems that formatName() is called with 'data[keys1[i]]' and so it returns 'data.*]'.

Maybe it could somehow push the tested key name in error message instead of globbing.

Validating a json-schema against the json-schema meta schema allows invalid json-schemas

Attempting to use is-my-json-valid in an API service I'm building, the service allows people to upload json-schemas and the first thing I want to check is if the schema itself is a valid v4 schema.

If I take the v4 meta schema from http://json-schema.org/documentation.html or I've put it in a gist here https://gist.github.com/bobthekingofegypt/53690b4206d4b689fc01.

I then use this to validate a basic schema like this

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "birthday": { "type": "string", "format": "date-time" },
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "astring" },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "country": { "type" : "string" }
      }
    }
  }
}

This schema is not valid as street_address has a type that is not a simpletype but is-my-json-valid is reporting it as valid. I've ran it through a few online validators and they are reporting the issue that type is not a member of simpletypes ref.

I don't know if this is maybe a use case that doesn't need to be supported though, I will try to see if I can work out what is happening.

Define formats with custom error messages

It would be good to have the ability to define a custom format which would allow to produce custom error messages. Suggested API is to return Error object and treat it as a validation failure and consider its message property as an error message:

function customFormat(value) {
  if (...) {
    return new Error('something is wrong')
  }
  return true
}

array index shows as * in field

Currently i get a field value like data.*.property when an item in a collection fails to validate. It would be great if I could get the index. E.g. data.2.property

What is the reason for formatName()

I have a JSON schema (and some data sets) which has ' ' (space) in the property name.

When validator find an error in one of these keys, in shows the property name as * (star), eg.

{
  field: 'data.*',
  message: 'pattern mismatch
}

I'd hoped for the validator to return field: 'data["some key with a space"]'.

What is the reason for using formatName? Is the idea to show the index of an array as a star instead of the actual index, or?

Request to expose error location-line and column

Hi,
I would like to have additional information on every error, describing WHERE is the text in the tested JSON file/string which failed validation.
The location info should include:
line number (most important),
column number (column is were the failed text token started),
number of characters of error text token (this parameter is nice-to-have)

Integer type is broken between 2^31 and 2^53

The validation fails for integer values between 2^31 and 2^53 (is-my-json-valid does not think these values are integers).

Examples:
2147483647 - integer (correct)
2147483648 - not an integer (fail)
9007199254740992 - not an integer (fail)
9007199254740994 - integer (correct)

This is especially significant, because the values currently returned by Date.now() are in that range.

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.