Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jsonschema

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsonschema - npm Package Compare versions

Comparing version 0.1.5 to 0.2.0

.idea/.name

262

lib/attribute.js
'use strict';
var helpers = require('./helpers');
var equal = require('deep-equal');
var Attribute = function Attribute(validator, name, schema, instance, propertyName, options) {
this.validator = validator;
this.name = name;
this.schema = schema;
this.value = schema[name];
this.propertyName = propertyName;
this.instance = instance;
this.options = options;
var attribute = {};
return this;
};
attribute.informativeProperties = ['id', 'default', 'description', 'title'];
attribute.argumentProperties = ['exclusiveMinimum', 'exclusiveMaximum','items','additionalItems','properties','additionalProperties','patternProperties'];
attribute.ignoreProperties = [].concat(attribute.informativeProperties, attribute.argumentProperties);
Attribute.prototype.createError = function (message) {
return helpers.createError(this.schema, this.name, this.propertyName, message);
};
var validators = attribute.validators = {};
Attribute.prototype.validate = function () {
// Ignored attributes, mostly due to that they are handled differently.
if (this.name === "exclusiveMinimum" || this.name === "exclusiveMaximum" || this.name === "default" || this.name === "description" || this.name === "title") {
return null;
function testType(instance, options, propertyName, type){
switch (type) {
case 'string': return (typeof instance=='string');
case 'number': return (typeof instance=='number');
case 'integer': return (typeof instance=='number') && instance%1===0;
case 'boolean': return (typeof instance=='boolean');
case 'object':
return (instance && (typeof instance)=='object' && Object.getPrototypeOf(instance)===Object.prototype);
case 'array': return (instance instanceof Array);
case 'null': return (instance===null);
case 'date': return (instance instanceof Date);
case 'any': return true;
}
var mName = 'validate' + helpers.capitalize(this.name);
if (this[mName]) {
return this[mName]();
} else {
console.log("WARNING: unsupported attribute:", this.name);
if(type && typeof type=='object'){
var errs = this.validateSchema(instance, type, options, propertyName);
return !(errs&&errs.length);
}
};
}
Attribute.prototype.validateType = function () {
var valid = false;
switch (this.value) {
case 'string':
valid = helpers.isString(this.instance);
break;
case 'number':
valid = helpers.isNumber(this.instance);
break;
case 'integer':
valid = helpers.isInteger(this.instance);
break;
case 'boolean':
valid = helpers.isBoolean(this.instance);
break;
case 'null':
valid = helpers.isNull(this.instance);
break;
case 'date':
valid = helpers.isDate(this.instance);
break;
case 'any':
valid = true;
break;
default:
break;
}
validators.type = function validateType(instance, schema, options, propertyName) {
var types = (schema.type instanceof Array)?schema.type:[schema.type];
// Ignore undefined instances
if (helpers.isDefined(this.instance) && !valid) {
return this.createError("is not " + this.value);
if (instance===undefined) return;
if(!types.some(testType.bind(this, instance, options, propertyName))) {
return "is not " + schema.type;
}

@@ -69,14 +43,12 @@ };

// Only applicable for numbers
Attribute.prototype.validateMinimum = function () {
validators.minimum = function validateMinimum(instance, schema) {
if (typeof instance!='number') return;
var valid = true;
if (helpers.isNumber(this.instance)) {
if (this.schema.exclusiveMinimum && this.schema.exclusiveMinimum === true) {
valid = this.instance > this.value;
} else {
valid = this.instance >= this.value;
}
if (schema.exclusiveMinimum && schema.exclusiveMinimum === true) {
valid = instance > schema.minimum;
} else {
valid = instance >= schema.minimum;
}
if (!valid) {
return this.createError("is not " + this.value);
return "is not " + schema.minimum;
}

@@ -86,32 +58,26 @@ };

// Only applicable for numbers
Attribute.prototype.validateMaximum = function () {
var valid = true;
if (helpers.isNumber(this.instance)) {
if (this.schema.exclusiveMaximum && this.schema.exclusiveMaximum === true) {
valid = this.instance < this.value;
} else {
valid = this.instance <= this.value;
}
validators.maximum = function validateMaximum(instance, schema) {
if (typeof instance!='number') return;
var valid;
if (schema.exclusiveMaximum && schema.exclusiveMaximum === true) {
valid = instance < schema.maximum;
} else {
valid = instance <= schema.maximum;
}
if (!valid) {
return this.createError("is not " + this.value);
return "is not " + schema.maximum;
}
};
Attribute.prototype.validateRequired = function () {
var valid = true;
if (!helpers.isDefined(this.instance) && this.value === true) {
return this.createError("is required");
// Only applicable for numbers
validators.divisibleBy = function validateDivisibleBy(instance, schema) {
if (typeof instance!='number') return;
if (instance % schema.divisibleBy) {
return "is not " + schema.maximum;
}
};
// Only applicable for numbers
Attribute.prototype.validate$ref = function () {
var valid = true;
if (helpers.isDefined(this.value) && this.validator.schemas[this.value]) {
return this.validator.validateSchema(this.instance, this.validator.schemas[this.value], this.options);
} else {
return this.createError("no such schema " + this.value);
validators.required = function validateRequired(instance, schema) {
if (instance===undefined && schema.required===true) {
return "is required";
}

@@ -121,18 +87,14 @@ };

// Only applicable for strings, ignored otherwise
Attribute.prototype.validatePattern = function () {
var valid = true;
if (helpers.isString(this.instance)) {
valid = (this.instance.match(this.value) !== null);
validators.pattern = function validatePattern(instance, schema) {
if (typeof instance!='string') return;
if(!instance.match(schema.pattern)) {
return "does not match pattern" + schema.pattern;
}
if (!valid) {
return this.createError("does not match pattern" + this.value);
}
};
// Only applicable for strings, ignored otherwise
Attribute.prototype.validateFormat = function () {
var valid = true;
valid = !helpers.isDefined(this.instance) || (helpers.isString(this.instance) && helpers.isFormat(this.instance, this.value));
if (!valid) {
return this.createError("\"" + this.instance + "\" does not conform to format " + this.value);
validators.format = function validateFormat(instance, schema) {
if(instance===undefined) return;
if (!helpers.isFormat(instance, schema.format)) {
return "\"" + instance + "\" does not conform to format " + schema.format;
}

@@ -142,20 +104,22 @@ };

// Only applicable for strings, ignored otherwise
Attribute.prototype.validateMinLength = function () {
var valid = true;
if (helpers.isString(this.instance)) {
valid = this.instance.length >= this.value;
validators.minLength = function validateMinLength(instance, schema) {
if (!(typeof instance=='string')) return;
if(!(instance.length >= schema.minLength)){
return "does not meet minimum length of " + schema.minLength;
}
if (!valid) {
return this.createError("does not meet minimum length of " + this.value);
}
};
// Only applicable for strings, ignored otherwise
Attribute.prototype.validateMaxLength = function () {
var valid = true;
if (helpers.isString(this.instance)) {
valid = this.instance.length <= this.value;
validators.maxLength = function validateMaxLength(instance, schema) {
if (!(typeof instance=='string')) return;
if(!(instance.length <= schema.maxLength)){
return "does not meet maximum length of " + schema.maxLength;
}
if (!valid) {
return this.createError("does not meet maximum length of " + this.value);
};
// Only applicable for arrays, ignored otherwise
validators.minItems = function validateMinItems(instance, schema) {
if (!(instance instanceof Array)) return;
if(!(instance.length >= schema.minItems)){
return "does not meet minimum length of " + schema.minItems;
}

@@ -165,40 +129,43 @@ };

// Only applicable for arrays, ignored otherwise
Attribute.prototype.validateMinItems = function () {
var valid = true;
if (helpers.isArray(this.instance)) {
valid = this.instance.length >= this.value;
validators.maxItems = function validateMaxItems(instance, schema) {
if (!(instance instanceof Array)) return;
if(!(instance.length <= schema.maxItems)){
return "does not meet maximum length of " + schema.maxItems;
}
if (!valid) {
return this.createError("does not meet minimum length of " + this.value);
}
};
// Only applicable for arrays, ignored otherwise
Attribute.prototype.validateMaxItems = function () {
var valid = true;
if (helpers.isArray(this.instance)) {
valid = this.instance.length <= this.value;
validators.uniqueItems = function validateUniqueItems(instance, schema) {
if (!(instance instanceof Array)) return;
function testArrays(v, i, a){
for(var j=i+1; j<a.length; j++) if(helpers.deepCompareStrict(v,a[j])) return false;
return true;
};
if(!instance.every(testArrays)){
return "contains duplicate item";
}
if (!valid) {
return this.createError("does not meet maximum length of " + this.value);
}
};
Attribute.prototype.validateEnum = function () {
var valid = false;
var i;
if (helpers.isArray(this.value)) {
for (i = 0; i <= this.value.length; i++) {
valid = equal(this.instance, this.value[i]);
// stop as soon as something is valid
if (valid) {
break;
validators.dependencies = function validateDependencies(instance, schema, options, propertyName) {
if (!instance || typeof instance!='object') return;
for(var property in schema.dependencies){
if(instance[property]===undefined) continue;
var dep = schema.dependencies[property];
var propPath = propertyName+helpers.makeSuffix(property);
if(typeof dep=='string'){
dep=[dep];
}
if(dep instanceof Array){
for(var i=0; i<dep.length; i++){
if(instance[dep[i]] === undefined){
return " property "+dep[i]+" not found, required by "+propPath;
}
}
return;
}else{
var errs = this.validateSchema(instance, dep, options, propPath);
if(errs&&errs.length){
return "does not meet dependency required by "+propPath;
}
}
if (!valid) {
return this.createError("is not one of enum values: " + this.value);
}
} else {
return this.createError("enum expects an array");
}

@@ -208,2 +175,19 @@ };

module.exports = Attribute;
validators.enum = function validateEnum(instance, schema) {
if (!(schema.enum instanceof Array)) {
return "enum expects an array";
}
if(!schema.enum.some(helpers.deepCompareStrict.bind(null, instance))){
return "is not one of enum values: " + schema.enum;
}
};
validators.disallow = function validateDisallow(instance, schema, options, propertyName) {
var types = (schema.disallow instanceof Array)?schema.disallow:[schema.disallow];
if (types.some(testType.bind(this, instance, options, propertyName))) {
return "is of prohibited type " + schema.type;
}
};
module.exports = attribute;
'use strict';
var createError = function (schema, validator, propertyName, message, instance) {
var createError = exports.createError = function createError(schema, validator, propertyName, message, instance) {
var result = {};

@@ -19,51 +19,3 @@ if (validator) result.validator = validator;

var capitalize = function (input) {
return input.charAt(0).toUpperCase() + input.slice(1);
};
var isString = function (input) {
return typeof input === 'string';
};
var isNull = function (input) {
return input === null;
};
var isFunction = function (input) {
return typeof input === 'function';
};
var isArray = function (input) {
return typeof input === 'object' && (input instanceof Array);
};
var isBoolean = function (input) {
return typeof input === 'boolean';
};
var isDefined = function (input) {
return typeof input !== 'undefined';
};
var isNumber = function (input) {
return typeof input === 'number';
};
var isInteger = function (input) {
return isNumber(input) && input % 1 === 0;
};
var isObject = function (input) {
return typeof input === 'object';
};
var isDate = function (input) {
return typeof input === 'object' && input instanceof Date;
};
var isRegExp = function (input) {
return typeof input === 'object' && input instanceof RegExp;
};
var FORMAT_REGEXPS = {
var FORMAT_REGEXPS = exports.FORMAT_REGEXPS = {
'date-time': /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/,

@@ -76,3 +28,3 @@ 'date': /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/,

'ipv6': /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
'uri': /^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/,
'uri': /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/,

@@ -85,3 +37,3 @@ 'color': /(#?([0-9A-Fa-f]{3,6})\b)|(aqua)|(black)|(blue)|(fuchsia)|(gray)|(green)|(lime)|(maroon)|(navy)|(olive)|(orange)|(purple)|(red)|(silver)|(teal)|(white)|(yellow)|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\))/,

'alphanumeric': /^[a-zA-Z0-9]+$/,
'utc-millisec': function (input) { return isString(input) && parseFloat(input) == parseInt(input, 10) && !isNaN(input); },
'utc-millisec': function (input) { return (typeof input=='string') && parseFloat(input) == parseInt(input, 10) && !isNaN(input); },
'regex': function (input) { return true; }, // TODO: Needs implementation

@@ -95,8 +47,8 @@ 'style': function (input) { return true; }, // TODO: Needs implementation

var isFormat = function (input, format) {
if (isDefined(FORMAT_REGEXPS[format]) === true) {
if (isRegExp(FORMAT_REGEXPS[format])) {
return input.match(FORMAT_REGEXPS[format]) !== null;
var isFormat = exports.isFormat = function isFormat(input, format) {
if (FORMAT_REGEXPS[format] !== undefined) {
if (FORMAT_REGEXPS[format] instanceof RegExp) {
return FORMAT_REGEXPS[format].test(input);
}
if (isFunction(FORMAT_REGEXPS[format])) {
if (typeof FORMAT_REGEXPS[format]=='function') {
return FORMAT_REGEXPS[format](input);

@@ -108,17 +60,31 @@ }

module.exports = {
createError: createError,
capitalize: capitalize,
isString: isString,
isNull: isNull,
isFunction: isFunction,
isArray: isArray,
isBoolean: isBoolean,
isDefined: isDefined,
isNumber: isNumber,
isInteger: isInteger,
isObject: isObject,
isDate: isDate,
isRegExp: isRegExp,
isFormat: isFormat
};
exports.makeSuffix = function makeSuffix(key){
key = key.toString();
// This function could be capable of outputting valid a ECMAScript string, but the
// resulting code for testing which form to use would be tens of thousands of characters long
// That means this will use the name form for some illegal forms
if(!key.match(/[.\s\[\]]/) && !key.match(/^[\d]/)) {
return '.'+key;
}else if(key.match(/^\d+$/)){
return '['+key+']';
}else{
return '['+JSON.stringify(key)+']';
}
}
exports.deepCompareStrict = function deepCompareStrict(a, b){
if(typeof a!=typeof b) return false;
if(a instanceof Array){
if(!(b instanceof Array)) return false;
if(a.length!=b.length) return false;
return a.every(function(v, i){return deepCompareStrict(a[i], b[i]);});
}
if(typeof a=='object'){
if(!a || !b) return a===b;
var akeys = Object.keys(a);
var bkeys = Object.keys(b);
if(akeys.length!=bkeys.length) return false;
return akeys.every(function(v){return deepCompareStrict(a[v], b[v]);});
}
return a===b;
}
'use strict';
var Attribute = require('./attribute');
var attribute = require('./attribute');
var helpers = require('./helpers');

@@ -8,202 +8,135 @@

this.schemas = {};
this.errors = [];
return this;
};
Validator.prototype.addSchema = function (schema, urn) {
var ourUrn = urn;
if (!schema) {
return;
}
if (!urn) {
ourUrn = schema.id;
}
if (ourUrn) {
this.schemas[ourUrn] = schema;
}
Validator.prototype.addSchema = function addSchema(schema, urn) {
if (!schema) return;
var ourUrn = urn||schema.id;
if (ourUrn) this.schemas[ourUrn] = schema;
return this.schemas[ourUrn];
};
Validator.prototype.setSchemas = function (schemas) {
Validator.prototype.setSchemas = function setSchemas(schemas) {
this.schemas = schemas;
};
Validator.prototype.addError = function (error) {
if (error) {
this.errors.push(error);
Validator.prototype.validate = function validate(instance, schema, options, propertyName) {
if(!propertyName) propertyName = 'instance';
if (schema) {
return this.validateSchema(instance, schema, options, propertyName);
}
throw new Error('no schema specified');
};
Validator.prototype.validate = function (instance, schema, options) {
if (helpers.isDefined(schema)) {
if (typeof schema.type === 'object' && (schema.type instanceof Array)) {
this.validateUnionType(instance, schema, options);
Validator.prototype.validateSchema = function validateSchema(instance, schema, options, propertyName) {
if(!schema){
return [helpers.createError(schema, undefined, undefined, "is undefined")];
}
var switchSchema = (typeof schema=='string')?schema:schema.$ref;
if(switchSchema) {
if (this.schemas[switchSchema]) {
return this.validateSchema(instance, this.schemas[switchSchema], options, propertyName);
} else {
this.validateSchema(instance, schema, options);
return [helpers.createError(schema, '$ref', propertyName, "no such schema " + switchSchema)];
}
}
return this.errors;
};
Validator.prototype.validateSchema = function (instance, schema, options) {
if (helpers.isDefined(schema.type)) {
switch (schema.type) {
case 'string':
case 'number':
case 'integer':
case 'boolean':
case 'null':
case 'date':
case 'any':
return this.validateProperty(instance, schema, options);
case 'object':
return this.validateObject(instance, schema, options);
case 'array':
return this.validateArray(instance, schema, options);
}
var errs = this.validateProperty(instance, schema, options, propertyName);
if(instance instanceof Array){
return errs.concat(this.validateArray(instance, schema, options, propertyName));
}else if(instance && (typeof instance)=='object' && Object.getPrototypeOf(instance)===Object.prototype){
return errs.concat(this.validateObject(instance, schema, options, propertyName));
}else{
return errs;
}
if (schema.$ref) {
return this.validateProperty(instance, schema, options);
}
};
Validator.prototype.validateProperty = function (instance, schema, options) {
var a;
var valid;
if (!helpers.isDefined(options)) {
options = {addError: true, skipAttributes: []};
} else {
if (!helpers.isDefined(options.addError) || helpers.isNull(options.addError)) {
options.addError = true;
}
if (!helpers.isDefined(options.skipAttributes) || helpers.isNull(options.skipAttributes)) {
options.skipAttributes = [];
}
}
var key, i;
// Validates each schema property against the instance
Validator.prototype.validateProperty = function validateProperty(instance, schema, options, propertyName) {
var self=this;
var errors = [];
var skipAttributes = options&&options.skipAttributes || [];
var keys = Object.keys(schema);
var keysLength = keys.length;
for (i = 0; i < keysLength; i++) {
key = keys[i];
if (options.skipAttributes.indexOf(key) === -1) {
a = new Attribute(this, key, schema, instance, options.propertyName, options);
valid = a.validate();
keys.forEach(function(key){
if (skipAttributes.indexOf(key)<0 && attribute.ignoreProperties.indexOf(key)<0) {
var validatorErr;
var validator = attribute.validators[key];
if (validator) {
validatorErr = validator.call(self, instance, schema, options, propertyName);
} else {
throw new Error("Unsupported attribute: "+key);
validatorErr = "WARNING: unsupported attribute: "+key;
}
if (options.addError === true) {
this.addError(valid);
if (validatorErr) {
errors.push(helpers.createError(schema, key, propertyName, validatorErr));
}
}
}
return valid;
});
return errors;
};
Validator.prototype.validateObject = function (instance, schema, options) {
var a;
var prop;
Validator.prototype.validateObject = function (instance, schema, options, propertyName) {
var errors = [];
// Only validate undefined's if they are required
if (!helpers.isDefined(instance)) {
if (helpers.isDefined(schema) && schema.required === true) {
this.addError(helpers.createError(schema, undefined, options.propertyName, "is required", instance));
if (instance===undefined) {
if (schema && schema.required===true) {
errors.push(helpers.createError(schema, undefined, propertyName, "is required", instance));
}
return;
return errors;
}
if (typeof instance !== 'object') {
if (!helpers.isDefined(options) || (helpers.isDefined(options) && options.addError === true)) {
this.addError(helpers.createError(schema, undefined, undefined, "not an object", instance));
}
} else {
var property, i;
if (helpers.isDefined(schema.properties)) {
this.validateAdditionalProperties(instance, schema, options);
var keys = Object.keys(schema.properties);
var keysLength = keys.length;
for (i = 0; i < keysLength; i++) {
property = keys[i];
if (helpers.isDefined(instance) && !helpers.isNull(instance) && helpers.isDefined(instance[property])) {
prop = instance[property];
} else {
prop = undefined;
}
this.validate(prop, schema.properties[property], {'propertyName': property, 'addError': true});
}
}
if (typeof instance!=='object' || instance&&Object.getPrototypeOf(instance)!==Object.prototype) {
errors.push(helpers.createError(schema, undefined, undefined, "not an object", instance));
return errors;
}
};
Validator.prototype.validateAdditionalProperties = function (instance, schema, options) {
if (!helpers.isDefined(schema.additionalProperties) || schema.additionalProperties === true) {
return;
}
var properties = schema.properties || {};
var property, i;
var keys = Object.keys(instance);
var keysLength = keys.length;
for (i = 0; i < keysLength; i++) {
property = keys[i];
if (!helpers.isDefined(schema.properties[property])) {
// true is the same as the default, an empty schema, which needs no validation
if (schema.additionalProperties!==undefined && schema.additionalProperties!==true) {
for(var property in instance){
if (properties[property]!==undefined) continue;
if (schema.additionalProperties === false) {
this.addError("Property " + property + " does not exist in the schema");
errors.push("Property " + property + " does not exist in the schema");
} else {
this.validate(instance[property], schema.additionalProperties, options);
var errs = this.validateSchema(instance[property], schema.additionalProperties, options, propertyName+helpers.makeSuffix(property));
if(errs&&errs.length) errors=errors.concat(errs);
}
}
}
};
// FIXME: This will fail if the schema doesn't have 'items' defined
Validator.prototype.validateArray = function (instance, schema, options) {
var a, i, len;
// Don't validate undefined's
if (!helpers.isDefined(instance)) {
return;
}
if (!(instance instanceof Array)) {
this.addError("not an array");
} else {
if (!options) {
options = {skipAttributes: ['items', 'type']};
} else {
if (options.skipAttributes === undefined || options.skipAttributes === null) {
options.skipAttributes = ['items', 'type'];
}
var patternProperties = schema.patternProperties || {};
for(var pattern in patternProperties){
var expr = new RegExp(pattern);
for(var property in instance){
if(!expr.test(property)) continue;
var errs = this.validateSchema(instance[property], schema.additionalProperties, options, propertyName+helpers.makeSuffix(property));
if(errs&&errs.length) errors=errors.concat(errs);
}
this.validateProperty(instance, schema, options);
options.skipAttributes = [];
for (i = 0, len = instance.length; i < len; i++) {
if (options && options.propertyName) {
options.propertyName = options.propertyName.concat("[", i, "]");
}
this.validate(instance[i], schema.items, options);
}
}
for(var property in properties){
var prop = (instance||undefined) && instance[property];
var errs = this.validate(prop, properties[property], options, propertyName+helpers.makeSuffix(property));
if(errs&&errs.length) errors=errors.concat(errs);
}
return errors;
};
Validator.prototype.validateUnionType = function (instance, schema, options) {
var i, len;
var numErrors = this.errors.length;
var startingNumErrors = numErrors;
var valid = false;
for (i = 0, len = schema.type.length; i < len; i++) {
if (typeof schema.type[i] === 'string') {
this.validateSchema(instance, {'type': schema.type[i]});
} else {
this.validateSchema(instance, schema.type[i]);
Validator.prototype.validateArray = function (instance, schema, options, propertyName) {
var self=this;
if (instance===undefined || !schema.items) return [];
var errors = [];
instance.every(function(value, i){
var items = (schema.items instanceof Array)?(schema.items[i]||schema.additionalItems||false):schema.items;
if(items===false){
errors.push("additionalItems not permitted");
return false;
}
if (this.errors.length === numErrors) {
valid = true;
break;
} else {
numErrors = this.errors.length - startingNumErrors;
}
}
if (valid) {
this.errors = this.errors.slice(0, startingNumErrors);
} else {
this.addError("not any of union type");
}
var errs = self.validateSchema(value, items, options, propertyName+"["+i+"]");
if(errs&&errs.length) errors=errors.concat(errs);
return true;
});
return errors;
};
module.exports = Validator;
{
"author": "Tom de Grunt <tom@degrunt.nl>",
"name": "jsonschema",
"version": "0.1.5",
"dependencies": {
"version": "0.2.0",
"dependencies": {},
"main": "./lib",
"devDependencies": {
"mocha": "~1.3",
"should": "~0.6.3",
"deep-equal": "0.0.0"
"should": "~0.6.3"
},
"main": "./lib",
"devDependencies": {},
"optionalDependencies": {},

@@ -13,0 +12,0 @@ "engines": {

@@ -28,5 +28,5 @@ [![Build Status](https://secure.travis-ci.org/tdegrunt/jsonschema.png)](http://travis-ci.org/tdegrunt/jsonschema)

| items | ✔ | ✔ |
| additionalItems | ✔ | |
| additionalItems | ✔ | ✔ |
| required | ✔ | ✔ |
| dependencies | ✔ | |
| dependencies | ✔ | ✔ |
| minimum | ✔ | ✔ |

@@ -38,3 +38,3 @@ | maximum | ✔ | ✔ |

| maxItems | ✔ | ✔ |
| uniqueItems | ✔ | |
| uniqueItems | ✔ | ✔ |
| pattern | ✔ | ✔ |

@@ -48,8 +48,8 @@ | minLength | ✔ | ✔ |

| format | ✔ | ✔ |
| divisibleBy | ✔ | |
| disallow | ✔ | |
| divisibleBy | ✔ | ✔ |
| disallow | ✔ | ✔ |
| extends | ✔ | |
| id | ✔ | ✔ |
| $ref | ✔ | ✔ |
| $schema | ✔ | |
| $schema | ✔ | |

@@ -113,2 +113,2 @@ ### Types

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

@@ -73,2 +73,28 @@ 'use strict';

});
});
describe('uniqueItems', function () {
beforeEach(function () {
this.validator = new Validator();
});
it('should validate if array has no duplicate items', function () {
return this.validator.validate([1], {'type': 'array', 'uniqueItems': true}).should.be.empty;
});
it('should validate if array has no duplicate objects', function () {
return this.validator.validate([1, 2, "1", "2", {a:1}, {a:1, b:1}], {'type': 'array', 'uniqueItems': true}).should.be.empty;
});
it('should not validate if array has duplicate numbers', function () {
return this.validator.validate([1, 2, 4, 1, 3, 5], {'type': 'array', 'uniqueItems': true}).should.not.be.empty;
});
it('should not validate if array has duplicate objects', function () {
return this.validator.validate([{a:1}, {a:1}], {'type': 'array', 'uniqueItems': true}).should.not.be.empty;
});
it('should validate if not an Array', function () {
return this.validator.validate(null, {'type': 'any', 'uniqueItems': true}).should.be.empty;
});
});
});

@@ -161,2 +161,20 @@ 'use strict';

describe('dividibleBy', function () {
beforeEach(function () {
this.validator = new Validator();
});
it('should validate if 0 is even', function () {
return this.validator.validate(2, {'type': 'number', 'divisibleBy': 2}).should.be.empty;
});
it('should validate if -2 is even', function () {
return this.validator.validate(-2, {'type': 'number', 'divisibleBy': 2}).should.be.empty;
});
it('should not validate 1 is even', function () {
return this.validator.validate(1, {'type': 'number', 'divisibleBy': 2}).should.not.be.empty;
});
});
describe('pattern', function () {

@@ -232,3 +250,2 @@ beforeEach(function () {

describe('description', function () {
beforeEach(function () {

@@ -242,2 +259,16 @@ this.validator = new Validator();

});
});
describe('disallow', function () {
beforeEach(function () {
this.validator = new Validator();
});
it('should prohibit specified types', function () {
this.validator.validate(1, {'type': 'any', 'disallow':'array'}).should.be.empty;
});
it('should not prohibit unprohibited types', function () {
this.validator.validate(1, {'type':'any', 'disallow':'array'}).should.be.empty;
});
});
});

@@ -114,5 +114,9 @@ 'use strict';

it('should not validate file:///Users/tdegrunt', function () {
this.validator.validate("file:///Users/tdegrunt", {'type': 'string', 'format': 'uri'}).should.not.be.empty;
it('should not validate relative URIs', function () {
this.validator.validate("tdegrunt", {'type': 'string', 'format': 'uri'}).should.not.be.empty;
});
it('should not validate with whitespace', function () {
this.validator.validate("The dog jumped", {'type': 'string', 'format': 'uri'}).should.not.be.empty;
});
});

@@ -217,2 +221,2 @@

});
});
});

@@ -51,6 +51,6 @@ 'use strict';

result[0].should.have.property('message', 'is not string');
result[0].should.have.property('property', 'lines[0]');
result[0].should.have.property('property', 'instance.lines[0]');
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc