jsonschema
Advanced tools
Comparing version 1.0.1 to 1.0.2
@@ -39,3 +39,3 @@ 'use strict'; | ||
* @param ctx | ||
* @return {String|null} | ||
* @return {ValidatorResult|null} | ||
*/ | ||
@@ -47,9 +47,15 @@ validators.type = function validateType (instance, schema, options, ctx) { | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var types = (schema.type instanceof Array) ? schema.type : [schema.type]; | ||
if (!types.some(this.testType.bind(this, instance, schema, options, ctx))) { | ||
return "is not of a type(s) " + types.map(function (v) { | ||
var list = types.map(function (v) { | ||
return v.id && ('<' + v.id + '>') || (v+''); | ||
}); | ||
result.addError({ | ||
name: 'type', | ||
argument: list, | ||
message: "is not of a type(s) " + list, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -67,3 +73,3 @@ | ||
* @param ctx | ||
* @return {String|null} | ||
* @return {ValidatorResult|null} | ||
*/ | ||
@@ -75,2 +81,3 @@ validators.anyOf = function validateAnyOf (instance, schema, options, ctx) { | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!(schema.anyOf instanceof Array)){ | ||
@@ -80,7 +87,12 @@ throw new SchemaError("anyOf must be an array"); | ||
if (!schema.anyOf.some(testSchema.bind(this, instance, options, ctx))) { | ||
return "is not any of " + schema.anyOf.map(function (v, i) { | ||
var list = schema.anyOf.map(function (v, i) { | ||
return (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
}); | ||
result.addError({ | ||
name: 'anyOf', | ||
argument: list, | ||
message: "is not any of " + list.join(','), | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -97,3 +109,2 @@ | ||
validators.allOf = function validateAllOf (instance, schema, options, ctx) { | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
// Ignore undefined instances | ||
@@ -106,2 +117,3 @@ if (instance === undefined) { | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var self = this; | ||
@@ -112,3 +124,7 @@ schema.allOf.forEach(function(v, i){ | ||
var msg = (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
result.addError('does not match allOf schema ' + msg + ' with ' + valid.errors.length + ' error[s]:'); | ||
result.addError({ | ||
name: 'allOf', | ||
argument: { id: msg, length: valid.errors.length, valid: valid }, | ||
message: 'does not match allOf schema ' + msg + ' with ' + valid.errors.length + ' error[s]:', | ||
}); | ||
result.importErrors(valid); | ||
@@ -136,9 +152,15 @@ } | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var count = schema.oneOf.filter(testSchema.bind(this, instance, options, ctx)).length; | ||
var list = schema.oneOf.map(function (v, i) { | ||
return (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
}); | ||
if (count!==1) { | ||
return "is not exactly one from " + schema.oneOf.map(function (v, i) { | ||
return (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
result.addError({ | ||
name: 'oneOf', | ||
argument: list, | ||
message: "is not exactly one from " + list.join(','), | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -179,3 +201,7 @@ | ||
if (schema.additionalProperties === false) { | ||
result.addError("additionalProperty '"+property+"' exists in instance when not allowed"); | ||
result.addError({ | ||
name: 'additionalProperties', | ||
argument: property, | ||
message: "additionalProperty " + JSON.stringify(property) + " exists in instance when not allowed", | ||
}); | ||
} else { | ||
@@ -251,11 +277,16 @@ var additionalProperties = schema.additionalProperties || {}; | ||
*/ | ||
validators.minProperties = function validateMinProperties (instance, schema) { | ||
validators.minProperties = function validateMinProperties (instance, schema, options, ctx) { | ||
if (!instance || typeof instance !== 'object') { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var keys = Object.keys(instance); | ||
if (!(keys.length >= schema.minProperties)) { | ||
return "does not meet minimum property length of " + schema.minProperties; | ||
result.addError({ | ||
name: 'minProperties', | ||
argument: schema.minProperties, | ||
message: "does not meet minimum property length of " + schema.minProperties, | ||
}) | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -269,11 +300,16 @@ | ||
*/ | ||
validators.maxProperties = function validateMaxProperties (instance, schema) { | ||
validators.maxProperties = function validateMaxProperties (instance, schema, options, ctx) { | ||
if (!instance || typeof instance !== 'object') { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var keys = Object.keys(instance); | ||
if (!(keys.length <= schema.maxProperties)) { | ||
return "does not meet maximum property length of " + schema.maxProperties; | ||
result.addError({ | ||
name: 'maxProperties', | ||
argument: schema.maxProperties, | ||
message: "does not meet maximum property length of " + schema.maxProperties, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -304,3 +340,6 @@ | ||
if (items === false) { | ||
result.addError("additionalItems not permitted"); | ||
result.addError({ | ||
name: 'items', | ||
message: "additionalItems not permitted", | ||
}); | ||
return false; | ||
@@ -322,6 +361,7 @@ } | ||
*/ | ||
validators.minimum = function validateMinimum (instance, schema) { | ||
validators.minimum = function validateMinimum (instance, schema, options, ctx) { | ||
if (typeof instance !== 'number') { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var valid = true; | ||
@@ -334,5 +374,9 @@ if (schema.exclusiveMinimum && schema.exclusiveMinimum === true) { | ||
if (!valid) { | ||
return "must have a minimum value of " + schema.minimum; | ||
result.addError({ | ||
name: 'minimum', | ||
argument: schema.minimum, | ||
message: "must have a minimum value of " + schema.minimum, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -346,6 +390,7 @@ | ||
*/ | ||
validators.maximum = function validateMaximum (instance, schema) { | ||
validators.maximum = function validateMaximum (instance, schema, options, ctx) { | ||
if (typeof instance !== 'number') { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var valid; | ||
@@ -358,5 +403,9 @@ if (schema.exclusiveMaximum && schema.exclusiveMaximum === true) { | ||
if (!valid) { | ||
return "must have a maximum value of " + schema.maximum; | ||
result.addError({ | ||
name: 'maximum', | ||
argument: schema.maximum, | ||
message: "must have a maximum value of " + schema.maximum, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -372,3 +421,3 @@ | ||
*/ | ||
validators.divisibleBy = function validateDivisibleBy (instance, schema) { | ||
validators.divisibleBy = function validateDivisibleBy (instance, schema, options, ctx) { | ||
if (typeof instance !== 'number') { | ||
@@ -382,6 +431,11 @@ return null; | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (instance / schema.divisibleBy % 1) { | ||
return "is not " + schema.divisibleBy; | ||
result.addError({ | ||
name: 'divisibleBy', | ||
argument: schema.divisibleBy, | ||
message: "is not divisible by (multiple of) " + JSON.stringify(schema.divisibleBy), | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -397,3 +451,3 @@ | ||
*/ | ||
validators.multipleOf = function validateMultipleOf (instance, schema) { | ||
validators.multipleOf = function validateMultipleOf (instance, schema, options, ctx) { | ||
if (typeof instance !== 'number') { | ||
@@ -407,6 +461,11 @@ return null; | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (instance / schema.multipleOf % 1) { | ||
return "is not " + schema.multipleOf; | ||
result.addError({ | ||
name: 'multipleOf', | ||
argument: schema.multipleOf, | ||
message: "is not a multiple of (divisible by) " + JSON.stringify(schema.multipleOf), | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -421,14 +480,20 @@ | ||
validators.required = function validateRequired (instance, schema, options, ctx) { | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (instance === undefined && schema.required === true) { | ||
return "is required"; | ||
}else if (instance && typeof instance==='object' && Array.isArray(schema.required)) { | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
result.addError({ | ||
name: 'required', | ||
message: "is required" | ||
}); | ||
} else if (instance && typeof instance==='object' && Array.isArray(schema.required)) { | ||
schema.required.forEach(function(n){ | ||
if(instance[n]===undefined){ | ||
result.addError("requires property "+JSON.stringify(n)); | ||
result.addError({ | ||
name: 'required', | ||
argument: n, | ||
message: "requires property " + JSON.stringify(n), | ||
}); | ||
} | ||
}); | ||
return result; | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -442,10 +507,15 @@ | ||
*/ | ||
validators.pattern = function validatePattern (instance, schema) { | ||
validators.pattern = function validatePattern (instance, schema, options, ctx) { | ||
if (typeof instance !== 'string') { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!instance.match(schema.pattern)) { | ||
return "does not match pattern " + schema.pattern; | ||
result.addError({ | ||
name: 'pattern', | ||
argument: schema.pattern, | ||
message: "does not match pattern " + JSON.stringify(schema.pattern), | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -477,6 +547,11 @@ | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!helpers.isFormat(instance, schema.format)) { | ||
return "does not conform to the '" + schema.format + "' format"; | ||
result.addError({ | ||
name: 'format', | ||
argument: schema.format, | ||
message: "does not conform to the " + JSON.stringify(schema.format) + " format", | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -490,10 +565,15 @@ | ||
*/ | ||
validators.minLength = function validateMinLength (instance, schema) { | ||
validators.minLength = function validateMinLength (instance, schema, options, ctx) { | ||
if (!(typeof instance === 'string')) { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!(instance.length >= schema.minLength)) { | ||
return "does not meet minimum length of " + schema.minLength; | ||
result.addError({ | ||
name: 'minLength', | ||
argument: schema.minLength, | ||
message: "does not meet minimum length of " + schema.minLength, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -507,10 +587,15 @@ | ||
*/ | ||
validators.maxLength = function validateMaxLength (instance, schema) { | ||
validators.maxLength = function validateMaxLength (instance, schema, options, ctx) { | ||
if (!(typeof instance === 'string')) { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!(instance.length <= schema.maxLength)) { | ||
return "does not meet maximum length of " + schema.maxLength; | ||
result.addError({ | ||
name: 'maxLength', | ||
argument: schema.maxLength, | ||
message: "does not meet maximum length of " + schema.maxLength, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -524,10 +609,15 @@ | ||
*/ | ||
validators.minItems = function validateMinItems (instance, schema) { | ||
validators.minItems = function validateMinItems (instance, schema, options, ctx) { | ||
if (!(instance instanceof Array)) { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!(instance.length >= schema.minItems)) { | ||
return "does not meet minimum length of " + schema.minItems; | ||
result.addError({ | ||
name: 'minItems', | ||
argument: schema.minItems, | ||
message: "does not meet minimum length of " + schema.minItems, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -541,10 +631,15 @@ | ||
*/ | ||
validators.maxItems = function validateMaxItems (instance, schema) { | ||
validators.maxItems = function validateMaxItems (instance, schema, options, ctx) { | ||
if (!(instance instanceof Array)) { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!(instance.length <= schema.maxItems)) { | ||
return "does not meet maximum length of " + schema.maxItems; | ||
result.addError({ | ||
name: 'maxItems', | ||
argument: schema.maxItems, | ||
message: "does not meet maximum length of " + schema.maxItems, | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -572,3 +667,6 @@ | ||
if (!instance.every(testArrays)) { | ||
result.addError("contains duplicate item"); | ||
result.addError({ | ||
name: 'uniqueItems', | ||
message: "contains duplicate item", | ||
}); | ||
} | ||
@@ -601,11 +699,14 @@ return result; | ||
*/ | ||
validators.uniqueItems = function validateUniqueItems (instance) { | ||
validators.uniqueItems = function validateUniqueItems (instance, schema, options, ctx) { | ||
if (!(instance instanceof Array)) { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!instance.every(testArrays)) { | ||
return "contains duplicate item"; | ||
result.addError({ | ||
name: 'uniqueItems', | ||
message: "contains duplicate item", | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -619,9 +720,9 @@ | ||
* @param ctx | ||
* @return {String|null|ValidatorResult} | ||
* @return {null|ValidatorResult} | ||
*/ | ||
validators.dependencies = function validateDependencies (instance, schema, options, ctx) { | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!instance || typeof instance != 'object') { | ||
return null; | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
for (var property in schema.dependencies) { | ||
@@ -639,3 +740,9 @@ if (instance[property] === undefined) { | ||
if (instance[prop] === undefined) { | ||
result.addError("property " + prop + " not found, required by " + childContext.propertyPath); | ||
result.addError({ | ||
// FIXME there's two different "dependencies" errors here with slightly different outputs | ||
// Can we make these the same? Or should we create different error types? | ||
name: 'dependencies', | ||
argument: childContext.propertyPath, | ||
message: "property " + prop + " not found, required by " + childContext.propertyPath, | ||
}); | ||
} | ||
@@ -647,3 +754,7 @@ }); | ||
if (res && res.errors.length) { | ||
result.addError("does not meet dependency required by " + childContext.propertyPath); | ||
result.addError({ | ||
name: 'dependencies', | ||
argument: childContext.propertyPath, | ||
message: "does not meet dependency required by " + childContext.propertyPath, | ||
}); | ||
result.importErrors(res); | ||
@@ -661,5 +772,5 @@ } | ||
* @param schema | ||
* @return {String|null} | ||
* @return {ValidatorResult|null} | ||
*/ | ||
validators['enum'] = function validateEnum (instance, schema) { | ||
validators['enum'] = function validateEnum (instance, schema, options, ctx) { | ||
if (!(schema['enum'] instanceof Array)) { | ||
@@ -671,6 +782,11 @@ throw new SchemaError("enum expects an array", schema); | ||
} | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
if (!schema['enum'].some(helpers.deepCompareStrict.bind(null, instance))) { | ||
return "is not one of enum values: " + schema['enum']; | ||
result.addError({ | ||
name: 'enum', | ||
argument: schema['enum'], | ||
message: "is not one of enum values: " + schema['enum'].join(','), | ||
}); | ||
} | ||
return null; | ||
return result; | ||
}; | ||
@@ -684,3 +800,3 @@ | ||
* @param ctx | ||
* @return {String|null|ValidatorResult} | ||
* @return {null|ValidatorResult} | ||
*/ | ||
@@ -697,3 +813,7 @@ validators.not = validators.disallow = function validateNot (instance, schema, options, ctx) { | ||
var schemaId = type && type.id && ('<' + type.id + '>') || type; | ||
result.addError("is of prohibited type " + schemaId); | ||
result.addError({ | ||
name: 'not', | ||
argument: schemaId, | ||
message: "is of prohibited type " + schemaId, | ||
}); | ||
} | ||
@@ -700,0 +820,0 @@ }); |
@@ -5,3 +5,3 @@ 'use strict'; | ||
var ValidationError = exports.ValidationError = function ValidationError (message, instance, schema, propertyPath) { | ||
var ValidationError = exports.ValidationError = function ValidationError (message, instance, schema, propertyPath, name, argument) { | ||
if (propertyPath) { | ||
@@ -23,2 +23,4 @@ this.property = propertyPath; | ||
} | ||
this.name = name; | ||
this.argument = argument; | ||
this.stack = this.toString(); | ||
@@ -39,4 +41,13 @@ }; | ||
ValidatorResult.prototype.addError = function addError(message) { | ||
var err = new ValidationError(message, this.instance, this.schema, this.propertyPath); | ||
ValidatorResult.prototype.addError = function addError(detail) { | ||
var err; | ||
if (typeof detail == 'string') { | ||
err = new ValidationError(detail, this.instance, this.schema, this.propertyPath); | ||
} else { | ||
if (!detail) throw new Error('Missing error detail'); | ||
if (!detail.message) throw new Error('Missing error message'); | ||
if (!detail.name) throw new Error('Missing validator type'); | ||
err = new ValidationError(detail.message, this.instance, this.schema, this.propertyPath, detail.name, detail.argument); | ||
} | ||
if (this.throwError) { | ||
@@ -50,3 +61,3 @@ throw err; | ||
ValidatorResult.prototype.importErrors = function importErrors(res) { | ||
if (typeof res == 'string') { | ||
if (typeof res == 'string' || (res && res.validatorType)) { | ||
this.addError(res); | ||
@@ -56,3 +67,3 @@ } else if (res && res.errors) { | ||
res.errors.forEach(function (v) { | ||
errs.push(v) | ||
errs.push(v); | ||
}); | ||
@@ -67,3 +78,3 @@ } | ||
Object.defineProperty(ValidatorResult.prototype, "valid", { get: function() { | ||
return !this.errors.length; | ||
return !this.errors.length; | ||
} }); | ||
@@ -70,0 +81,0 @@ |
@@ -75,2 +75,3 @@ 'use strict'; | ||
this.addSubSchemaArray(ourBase, ((schema.items instanceof Array)?schema.items:[schema.items])); | ||
this.addSubSchemaArray(ourBase, ((schema.extends instanceof Array)?schema.extends:[schema.extends])); | ||
this.addSubSchema(ourBase, schema.additionalItems); | ||
@@ -77,0 +78,0 @@ this.addSubSchemaObject(ourBase, schema.properties); |
{ | ||
"author": "Tom de Grunt <tom@degrunt.nl>", | ||
"name": "jsonschema", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"dependencies": { | ||
@@ -6,0 +6,0 @@ }, |
@@ -1,2 +0,2 @@ | ||
[![Build Status](https://secure.travis-ci.org/tdegrunt/jsonschema.png)](http://travis-ci.org/tdegrunt/jsonschema) | ||
[![Build Status](https://secure.travis-ci.org/tdegrunt/jsonschema.svg)](http://travis-ci.org/tdegrunt/jsonschema) | ||
@@ -3,0 +3,0 @@ # jsonschema |
50250
1301