jsonschema
Advanced tools
Comparing version 0.2.1 to 0.3.0
@@ -8,3 +8,3 @@ 'use strict'; | ||
attribute.informativeProperties = ['id', 'default', 'description', 'title']; | ||
attribute.argumentProperties = ['exclusiveMinimum', 'exclusiveMaximum', 'items', 'additionalItems', 'properties', 'additionalProperties', 'patternProperties']; | ||
attribute.argumentProperties = ['exclusiveMinimum', 'exclusiveMaximum', 'items', 'additionalItems', 'properties', 'additionalProperties', 'patternProperties', 'extends']; | ||
attribute.ignoreProperties = [].concat(attribute.informativeProperties, attribute.argumentProperties); | ||
@@ -14,3 +14,11 @@ | ||
/** | ||
* Tests whether the instance if of a certain type. | ||
* @private | ||
* @param instance | ||
* @param options | ||
* @param propertyName | ||
* @param type | ||
* @return {boolean} | ||
*/ | ||
var testType = function (instance, options, propertyName, type) { | ||
@@ -26,4 +34,5 @@ switch (type) { | ||
return (typeof instance === 'boolean'); | ||
// TODO: fix this - see #15 | ||
case 'object': | ||
return (instance && (typeof instance) === 'object'); | ||
return (instance && (typeof instance) === 'object' && !(instance instanceof Array) && !(instance instanceof Date)); | ||
case 'array': | ||
@@ -46,2 +55,10 @@ return (instance instanceof Array); | ||
/** | ||
* Validates whether the instance if of a certain type | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @return {String|null} | ||
*/ | ||
validators.type = function validateType(instance, schema, options, propertyName) { | ||
@@ -59,3 +76,8 @@ // Ignore undefined instances | ||
// Only applicable for numbers | ||
/** | ||
* Validates minimum and exclusiveMinimum when the type of the instance value is a number. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.minimum = function validateMinimum(instance, schema) { | ||
@@ -77,3 +99,8 @@ if (typeof instance !== 'number') { | ||
// Only applicable for numbers | ||
/** | ||
* Validates maximum and exclusiveMaximum when the type of the instance value is a number. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.maximum = function validateMaximum(instance, schema) { | ||
@@ -95,3 +122,8 @@ if (typeof instance !== 'number') { | ||
// Only applicable for numbers | ||
/** | ||
* Validates divisibleBy when the type of the instance value is a number. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.divisibleBy = function validateDivisibleBy(instance, schema) { | ||
@@ -101,8 +133,19 @@ if (typeof instance !== 'number') { | ||
} | ||
if (instance % schema.divisibleBy) { | ||
return "is not " + schema.maximum; | ||
if (schema.divisibleBy == 0) { | ||
return "divisibleBy can't be zero"; | ||
} | ||
if (instance / schema.divisibleBy % 1) { | ||
return "is not " + schema.divisibleBy; | ||
} | ||
return null; | ||
}; | ||
/** | ||
* Validates whether the instance value is present. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.required = function validateRequired(instance, schema) { | ||
@@ -115,3 +158,8 @@ if (instance === undefined && schema.required === true) { | ||
// Only applicable for strings, ignored otherwise | ||
/** | ||
* Validates whether the instance value matches the regular expression, when the instance value is a string. | ||
* @param instance | ||
* @param schema | ||
* @return {*} | ||
*/ | ||
validators.pattern = function validatePattern(instance, schema) { | ||
@@ -127,3 +175,20 @@ if (typeof instance !== 'string') { | ||
// Only applicable for strings, ignored otherwise | ||
/** | ||
* Validates whether the instance value is of a certain defined format, when the instance value is a string. | ||
* The following format are supported: | ||
* - date-time | ||
* - date | ||
* - time | ||
* - ip-address | ||
* - ipv6 | ||
* - uri | ||
* - color | ||
* - host-name | ||
* - alpha | ||
* - alpha-numeric | ||
* - utc-millisec | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.format = function validateFormat(instance, schema) { | ||
@@ -139,3 +204,8 @@ if (instance === undefined) { | ||
// Only applicable for strings, ignored otherwise | ||
/** | ||
* Validates whether the instance value is at least of a certain length, when the instance value is a string. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.minLength = function validateMinLength(instance, schema) { | ||
@@ -151,3 +221,8 @@ if (!(typeof instance === 'string')) { | ||
// Only applicable for strings, ignored otherwise | ||
/** | ||
* Validates whether the instance value is at most of a certain length, when the instance value is a string. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.maxLength = function validateMaxLength(instance, schema) { | ||
@@ -163,3 +238,8 @@ if (!(typeof instance === 'string')) { | ||
// Only applicable for arrays, ignored otherwise | ||
/** | ||
* Validates whether instance contains at least a minimum number of items, when the instance is an Array. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.minItems = function validateMinItems(instance, schema) { | ||
@@ -175,3 +255,8 @@ if (!(instance instanceof Array)) { | ||
// Only applicable for arrays, ignored otherwise | ||
/** | ||
* Validates whether instance contains no more than a maximum number of items, when the instance is an Array. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.maxItems = function validateMaxItems(instance, schema) { | ||
@@ -187,3 +272,10 @@ if (!(instance instanceof Array)) { | ||
// @private | ||
/** | ||
* Deep compares arrays for duplicates | ||
* @param v | ||
* @param i | ||
* @param a | ||
* @private | ||
* @return {boolean} | ||
*/ | ||
function testArrays(v, i, a) { | ||
@@ -199,4 +291,8 @@ var j, len; | ||
// Only applicable for arrays, ignored otherwise | ||
validators.uniqueItems = function validateUniqueItems(instance, schema) { | ||
/** | ||
* Validates whether there are no duplicates, when the instance is an Array. | ||
* @param instance | ||
* @return {String|null} | ||
*/ | ||
validators.uniqueItems = function validateUniqueItems(instance) { | ||
if (!(instance instanceof Array)) { | ||
@@ -212,2 +308,10 @@ return null; | ||
/** | ||
* Validate for the presence of dependency properties, if the instance is an object. | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @return {String|null} | ||
*/ | ||
validators.dependencies = function validateDependencies(instance, schema, options, propertyName) { | ||
@@ -246,3 +350,9 @@ if (!instance || typeof instance !== 'object') { | ||
/** | ||
* Validates whether the instance value is one of the enumerated values, if the instance is an array. | ||
* | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.enum = function validateEnum(instance, schema) { | ||
@@ -258,2 +368,10 @@ if (!(schema.enum instanceof Array)) { | ||
/** | ||
* Validates whether the instance if of a prohibited type. | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @return {String|null} | ||
*/ | ||
validators.disallow = function validateDisallow(instance, schema, options, propertyName) { | ||
@@ -260,0 +378,0 @@ var types = (schema.disallow instanceof Array) ? schema.disallow : [schema.disallow]; |
'use strict'; | ||
/** @type Validator */ | ||
var Validator = require('./validator'); | ||
/** | ||
* Validation Environment | ||
* @name Environment | ||
* @constructor | ||
*/ | ||
var Environment = function Environment() { | ||
@@ -10,2 +16,8 @@ this.schemas = {}; | ||
/** | ||
* Adds a schema to the environment | ||
* @param schema | ||
* @param urn | ||
* @return {Object} | ||
*/ | ||
Environment.prototype.addSchema = function (schema, urn) { | ||
@@ -27,2 +39,8 @@ var ourUrn = urn; | ||
/** | ||
* Validates instance against the provided schema | ||
* @param instance | ||
* @param schema | ||
* @return {Array} | ||
*/ | ||
Environment.prototype.validate = function (instance, schema) { | ||
@@ -34,2 +52,2 @@ var v = new Validator(); | ||
module.exports = Environment; | ||
module.exports = Environment; |
@@ -47,13 +47,8 @@ 'use strict'; | ||
'regex': function (input) { | ||
// TODO: Needs implementation | ||
return true; | ||
var result = true; | ||
try { new RegExp(input); } catch(e) { result = false; } | ||
return result; | ||
}, | ||
'style': function (input) { | ||
// TODO: Needs implementation | ||
return true; | ||
}, | ||
'phone': function (input) { | ||
// TODO: Needs implementation | ||
return true; | ||
} | ||
'style': /\s*(.+?):\s*([^;]+);?/g, | ||
'phone': /^\+(?:[0-9] ?){6,14}[0-9]$/ | ||
}; | ||
@@ -120,1 +115,55 @@ | ||
}; | ||
module.exports.deepMerge = function deepMerge (target, src) { | ||
var array = Array.isArray(src) | ||
var dst = array && [] || {} | ||
if (array) { | ||
target = target || [] | ||
dst = dst.concat(target) | ||
src.forEach(function(e, i) { | ||
if (typeof e === 'object') { | ||
dst[i] = deepMerge(target[i], e) | ||
} else { | ||
if (target.indexOf(e) === -1) { | ||
dst.push(e) | ||
} | ||
} | ||
}) | ||
} else { | ||
if (target && typeof target === 'object') { | ||
Object.keys(target).forEach(function (key) { | ||
dst[key] = target[key] | ||
}) | ||
} | ||
Object.keys(src).forEach(function (key) { | ||
if (typeof src[key] !== 'object' || !src[key]) { | ||
dst[key] = src[key] | ||
} | ||
else { | ||
if (!target[key]) { | ||
dst[key] = src[key] | ||
} else { | ||
dst[key] = deepMerge(target[key], src[key]) | ||
} | ||
} | ||
}) | ||
} | ||
return dst | ||
} | ||
exports.objectGetPath = function(o, s) { | ||
s = s.replace(/\[(\w+)\]/g, '/$1'); | ||
s = s.replace(/^\//, ''); | ||
var a = s.split('/'); | ||
while (a.length) { | ||
var n = a.shift(); | ||
if (n in o) { | ||
o = o[n]; | ||
} else { | ||
return; | ||
} | ||
} | ||
return o; | ||
}; |
@@ -6,2 +6,7 @@ 'use strict'; | ||
/** | ||
* Creates a new Validator object | ||
* @name Validator | ||
* @constructor | ||
*/ | ||
var Validator = function Validator() { | ||
@@ -12,2 +17,8 @@ this.schemas = {}; | ||
/** | ||
* Adds a schema with a certain urn to the Validator instance. | ||
* @param schema | ||
* @param urn | ||
* @return {Object} | ||
*/ | ||
Validator.prototype.addSchema = function addSchema(schema, urn) { | ||
@@ -24,2 +35,6 @@ if (!schema) { | ||
/** | ||
* Sets all the schemas of the Validator instance. | ||
* @param schemas | ||
*/ | ||
Validator.prototype.setSchemas = function setSchemas(schemas) { | ||
@@ -29,2 +44,18 @@ this.schemas = schemas; | ||
/** | ||
* Returns the schema of a certain urn | ||
* @param urn | ||
*/ | ||
Validator.prototype.getSchema = function getSchema(urn) { | ||
return this.schemas[urn]; | ||
}; | ||
/** | ||
* Validates instance against the provided schema | ||
* @param instance | ||
* @param schema | ||
* @param [options] | ||
* @param [propertyName] | ||
* @return {Array} | ||
*/ | ||
Validator.prototype.validate = function validate(instance, schema, options, propertyName) { | ||
@@ -35,2 +66,5 @@ if (!propertyName) { | ||
if (schema) { | ||
if (!this.schemas['#']) { | ||
this.addSchema(schema, '#'); | ||
} | ||
return this.validateSchema(instance, schema, options, propertyName); | ||
@@ -41,2 +75,11 @@ } | ||
/** | ||
* Validates an instance against the schema (the actual work horse) | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @private | ||
* @return {Array} | ||
*/ | ||
Validator.prototype.validateSchema = function validateSchema(instance, schema, options, propertyName) { | ||
@@ -46,2 +89,13 @@ if (!schema) { | ||
} | ||
if (schema.extends) { | ||
if(schema.extends instanceof Array) { | ||
schema.extends.forEach(function(s) { | ||
schema = helpers.deepMerge(schema, s); | ||
}); | ||
} else { | ||
schema = helpers.deepMerge(schema, schema.extends); | ||
} | ||
} | ||
var switchSchema = (typeof schema === 'string') ? schema : schema.$ref; | ||
@@ -52,2 +106,6 @@ if (switchSchema) { | ||
} | ||
if (switchSchema.substr(0,2) == '#/') { | ||
schema = helpers.objectGetPath(this.schemas['#'], switchSchema.substr(1)); | ||
return this.validateSchema(instance, schema, options, propertyName); | ||
} | ||
return [helpers.createError(schema, '$ref', propertyName, "no such schema " + switchSchema)]; | ||
@@ -59,3 +117,4 @@ } | ||
} | ||
if (instance && (typeof instance) === 'object' && Object.getPrototypeOf(instance) === Object.prototype) { | ||
// TODO: fix this - see #15 | ||
if (instance && (typeof instance) === 'object' && !(instance instanceof Array) && !(instance instanceof Date)) { | ||
return errs.concat(this.validateObject(instance, schema, options, propertyName)); | ||
@@ -66,3 +125,11 @@ } | ||
// Validates each schema property against the instance | ||
/** | ||
* Validates each schema property against the instance | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @private | ||
* @return {Array} | ||
*/ | ||
Validator.prototype.validateProperty = function validateProperty(instance, schema, options, propertyName) { | ||
@@ -91,2 +158,11 @@ var self = this; | ||
/** | ||
* Validates an object against the schema | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @private | ||
* @return {Array} | ||
*/ | ||
Validator.prototype.validateObject = function (instance, schema, options, propertyName) { | ||
@@ -111,20 +187,3 @@ var errors = []; | ||
// true is the same as the default, an empty schema, which needs no validation | ||
if (schema.additionalProperties !== undefined && schema.additionalProperties !== true) { | ||
for (property in instance) { | ||
if (instance.hasOwnProperty(property)) { | ||
if (properties[property] !== undefined) { | ||
continue; | ||
} | ||
if (schema.additionalProperties === false) { | ||
errors.push("Property " + property + " does not exist in the schema"); | ||
} else { | ||
errs = this.validateSchema(instance[property], schema.additionalProperties, options, propertyName + helpers.makeSuffix(property)); | ||
if (errs && errs.length) { | ||
errors = errors.concat(errs); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
var lookedAtPatternProperties = []; | ||
@@ -141,2 +200,22 @@ var patternProperties = schema.patternProperties || {}; | ||
} | ||
lookedAtPatternProperties.push(property); | ||
errs = this.validateSchema(instance[property], schema.patternProperties[pattern], options, propertyName + helpers.makeSuffix(property)); | ||
if (errs && errs.length) { | ||
errors = errors.concat(errs); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// true is the same as the default, an empty schema, which needs no validation | ||
if (schema.additionalProperties !== undefined && schema.additionalProperties !== true) { | ||
for (property in instance) { | ||
if (instance.hasOwnProperty(property)) { | ||
if (properties[property] !== undefined || lookedAtPatternProperties.indexOf(property) >= 0) { | ||
continue; | ||
} | ||
if (schema.additionalProperties === false) { | ||
errors.push("Property " + property + " does not exist in the schema"); | ||
} else { | ||
errs = this.validateSchema(instance[property], schema.additionalProperties, options, propertyName + helpers.makeSuffix(property)); | ||
@@ -163,2 +242,11 @@ if (errs && errs.length) { | ||
/** | ||
* Validates an array against the schema | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param propertyName | ||
* @private | ||
* @return {Array} | ||
*/ | ||
Validator.prototype.validateArray = function (instance, schema, options, propertyName) { | ||
@@ -171,3 +259,3 @@ var self = this; | ||
instance.every(function (value, i) { | ||
var items = (schema.items instanceof Array) ? (schema.items[i] || schema.additionalItems || false) : schema.items; | ||
var items = (schema.items instanceof Array) ? (schema.items[i] || schema.additionalItems) : schema.items; | ||
if (items === false) { | ||
@@ -177,7 +265,9 @@ errors.push("additionalItems not permitted"); | ||
} | ||
var errs = self.validateSchema(value, items, options, propertyName + "[" + i + "]"); | ||
if (errs && errs.length) { | ||
errors = errors.concat(errs); | ||
if (items) { | ||
var errs = self.validateSchema(value, items, options, propertyName + "[" + i + "]"); | ||
if (errs && errs.length) { | ||
errors = errors.concat(errs); | ||
} | ||
return true; | ||
} | ||
return true; | ||
}); | ||
@@ -184,0 +274,0 @@ return errors; |
{ | ||
"author": "Tom de Grunt <tom@degrunt.nl>", | ||
"name": "jsonschema", | ||
"version": "0.2.1", | ||
"dependencies": {}, | ||
"version": "0.3.0", | ||
"dependencies": { | ||
}, | ||
"main": "./lib", | ||
@@ -15,3 +16,8 @@ "devDependencies": { | ||
}, | ||
"keywords": ["json", "schema", "jsonschema", "validator"], | ||
"keywords": [ | ||
"json", | ||
"schema", | ||
"jsonschema", | ||
"validator" | ||
], | ||
"repository": { | ||
@@ -23,4 +29,4 @@ "type": "git", | ||
"scripts": { | ||
"test": "./node_modules/.bin/mocha" | ||
"test": "./node_modules/.bin/mocha -R spec" | ||
} | ||
} |
@@ -25,3 +25,3 @@ [![Build Status](https://secure.travis-ci.org/tdegrunt/jsonschema.png)](http://travis-ci.org/tdegrunt/jsonschema) | ||
| properties | ✔ | ✔ | | ||
| patternProperties | ✔ | | | ||
| patternProperties | ✔ | ✔ | | ||
| additionalProperties | ✔ | ✔ | | ||
@@ -43,12 +43,12 @@ | items | ✔ | ✔ | | ||
| enum | ✔ | ✔ | | ||
| default | ✔ | | | ||
| title | ✔ | ✔ | no function, only for commenting schema | ||
| description | ✔ | ✔ | no function, only for commenting schema | ||
| default | ✔ | ✔ | informational only | ||
| title | ✔ | ✔ | informational only | ||
| description | ✔ | ✔ | informational only | ||
| format | ✔ | ✔ | | ||
| divisibleBy | ✔ | ✔ | | ||
| disallow | ✔ | ✔ | | ||
| extends | ✔ | | | ||
| id | ✔ | ✔ | | ||
| extends | ✔ | ✔ | | ||
| id | ✔ | ✔ | informational only | ||
| $ref | ✔ | ✔ | | ||
| $schema | ✔ | | | ||
| $schema | ✔ | | ignored | ||
@@ -78,6 +78,6 @@ ### Types | ||
| `utc-millisec` | ✔ | ✔ | Any number (integer or float) is allowed | ||
| `regex` | ✔ | ✔ | Any string is allowed | ||
| `regex` | ✔ | ✔ | We test for valid regular expression | ||
| `color` | ✔ | ✔ | | ||
| `style` | ✔ | ✔ | Any string is allowed | ||
| `phone` | ✔ | ✔ | Any string is allowed | ||
| `style` | ✔ | ✔ | | ||
| `phone` | ✔ | ✔ | Should follow [http://en.wikipedia.org/wiki/E.123](E.123) standard. | ||
| `uri` | ✔ | ✔ | | ||
@@ -91,2 +91,10 @@ | `email` | ✔ | ✔ | | ||
## Tests | ||
Uses [https://github.com/Julian/JSON-Schema-Test-Suite](JSON Schema Test Suite) as well as our own. | ||
You'll need to update and init the git submodules: | ||
git submodule update --init | ||
npm test | ||
## License | ||
@@ -93,0 +101,0 @@ |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
119
28830
8
789
1