diff --git a/lib/revalidator.js b/lib/revalidator.js index 1faa25f..dd19999 100644 --- a/lib/revalidator.js +++ b/lib/revalidator.js @@ -97,7 +97,8 @@ uniqueItems: "must hold a unique set of values", format: "is not a valid %{expected}", conform: "must conform to given constraint", - type: "must be of %{expected} type" + type: "must be of %{expected} type", + additionalProperties: "extra properties are not allowed" }; validate.messages['enum'] = "must be present in given enumerator"; @@ -158,7 +159,7 @@ return obj; }; - function validateObject(object, schema, options, errors) { + function validateObject(object, schema, options, errors, path) { var props, allProps = Object.keys(object), visitedProps = []; @@ -168,7 +169,7 @@ for (var p in props) { if (props.hasOwnProperty(p)) { visitedProps.push(p); - validateProperty(object, object[p], p, props[p], options, errors); + validateProperty(object, object[p], p, props[p], options, errors, path); } } } @@ -185,7 +186,7 @@ if (object.hasOwnProperty(k)) { visitedProps.push(k); if (re.exec(k) !== null) { - validateProperty(object, object[k], p, props[p], options, errors); + validateProperty(object, object[k], p, props[p], options, errors, path); } } } @@ -204,20 +205,20 @@ // Prevent additional properties; each unvisited property is therefore an error if (schema.additionalProperties === false && unvisitedProps.length > 0) { for (i = 0, l = unvisitedProps.length; i < l; i++) { - error("additionalProperties", unvisitedProps[i], object[unvisitedProps[i]], false, errors); + error("additionalProperties", unvisitedProps[i], object[unvisitedProps[i]], false, errors, path); } } // additionalProperties is a schema and validate unvisited properties against that schema else if (typeof schema.additionalProperties == "object" && unvisitedProps.length > 0) { for (i = 0, l = unvisitedProps.length; i < l; i++) { - validateProperty(object, object[unvisitedProps[i]], unvisitedProps[i], schema.unvisitedProperties, options, errors); + validateProperty(object, object[unvisitedProps[i]], unvisitedProps[i], schema.unvisitedProperties, options, errors, path); } } } }; - function validateProperty(object, value, property, schema, options, errors) { + function validateProperty(object, value, property, schema, options, errors, path) { var format, valid, spec, @@ -225,30 +226,44 @@ function constrain(name, value, assert) { if (schema[name] !== undefined && !assert(value, schema[name])) { - error(name, property, value, schema, errors); + error(name, property, value, schema, errors, path); } } if (value === undefined) { if (schema.required && schema.type !== 'any') { - return error('required', property, undefined, schema, errors); + error('required', property, undefined, schema, errors, path); + + if (schema.properties || schema.patternProperties || schema.additionalProperties) { + validateObject({}, schema, options, errors, (!path ? property : path) + "."); + } + else if(schema.items && schema.items.properties){ + checkType([], schema.type, function(err, type){ + if(!err && type=='array'){ + validateObject({}, schema.items, options, errors, (!path ? property : path) + "[0]."); + } + }); + } + return; } else { return; } } if (options.cast) { - if (('integer' === schema.type || 'number' === schema.type) && value == +value) { - value = +value; - } - - if ('boolean' === schema.type) { - if ('true' === value || '1' === value || 1 === value) { - value = true; + if(schema.type !== undefined && schema.type !== null){ + if((schema.type.indexOf('integer') > -1 || schema.type.indexOf('number') > -1) && value == +value){ + value = +value; } - if ('false' === value || '0' === value || 0 === value) { - value = false; + if (schema.type.indexOf('boolean') > -1){ + if ('true' === value || '1' === value || 1 === value) { + value = true; + } + + if ('false' === value || '0' === value || 0 === value) { + value = false; + } } } } @@ -260,30 +275,40 @@ if (!spec) { spec = validate.formats[format] } if (!spec) { if (options.validateFormatsStrict) { - return error('format', property, value, schema, errors); + return error('format', property, value, schema, errors, path); } } else { if (!spec.test(value)) { - return error('format', property, value, schema, errors); + return error('format', property, value, schema, errors, path); } } } - if (schema['enum'] && schema['enum'].indexOf(value) === -1) { - error('enum', property, value, schema, errors); + if (schema['enum']){ + if(schema['type']=='array' && isArray(value)){ + for(var i=0; i