diff --git a/lib/revalidator.js b/lib/revalidator.js index 1faa25f..08e3f69 100644 --- a/lib/revalidator.js +++ b/lib/revalidator.js @@ -26,7 +26,8 @@ // ({}) in this case. // function validate(object, schema, options) { - options = mixin({}, options, validate.defaults); + options = mixin({}, validate.defaults, options); + var errors = []; validateObject(object, schema, options, errors); @@ -76,7 +77,25 @@ * Default: true *

*/ - validateFormatExtensions: true + validateFormatExtensions: true, + /** + *

+ * When {@link #addMissingDefaults} is true, + * if property is missing and it has a default value it will be added to the object. + *

+ * Default: false + *

+ */ + addMissingDefaults: false, + /** + *

+ * When {@link #deleteUnknowProperties} is true, + * if property is not declared in schema it is deleted from object. + *

+ * Default: false + *

+ */ + deleteUnknowProperties: false }; /** @@ -193,6 +212,16 @@ } } + // deleteUnknowProperties + if(options.deleteUnknowProperties){ + props = schema.properties ? Object.keys(schema.properties) : []; + props = props.concat(schema.patternProperties ? Object.keys(schema.patternProperties) : []); + for (var p in object){ + if (props.indexOf(p) === -1) + delete object[p]; + } + }; + // see 5.4 if (undefined !== schema.additionalProperties) { var i, l; @@ -201,6 +230,7 @@ return -1 === visitedProps.indexOf(k); }); + // 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++) { @@ -230,7 +260,12 @@ } if (value === undefined) { - if (schema.required && schema.type !== 'any') { + if(schema.default !== undefined && options.addMissingDefaults){ + if (typeof schema.default === 'function') + object[property] = value = schema.default(); + else + object[property] = value = schema.default; + }else if (schema.required && schema.type !== 'any') { return error('required', property, undefined, schema, errors); } else { return; diff --git a/test/validator-test.js b/test/validator-test.js index 0d2590d..e6e28eb 100644 --- a/test/validator-test.js +++ b/test/validator-test.js @@ -231,7 +231,10 @@ vows.describe('revalidator', { category: { type: 'string' }, palindrome: {type: 'string', conform: function(val) { return val == val.split("").reverse().join(""); } - } + }, + printed_at: { type: 'string', default: Date}, + printed_copies: { type: 'number', default: 100}, + shipped_copies: { type: 'number', default: function(){return 50}}, }, patternProperties: { '^_': { @@ -273,6 +276,37 @@ vows.describe('revalidator', { "and an error concerning the 'required' attribute": assertHasError('required'), "and the error message defined": assertHasErrorMsg('required', "is essential for survival") }, + "and if it has a missing default property": { + topic: function (object, schema) { + var duble = clone(object); + delete duble.printed_copies; + delete duble.printed_at; + delete duble.shipped_copies; + return { + valid: revalidator.validate(duble, schema, { addMissingDefaults: true }).valid, + target: duble + } + }, + "add missing properties to object with default values": function(res){ + assert.ok(res.valid); + assert.equal(res.target.printed_copies, 100); + assert.equal(res.target.shipped_copies, 50); + } + }, + "and if it has properties not declared in schema":{ + topic: function(object, schema){ + var duble = clone(object); + duble.not_here = 'ohno'; + return { + valid: revalidator.validate(duble, schema, { deleteUnknowProperties: true }).valid, + target: duble + } + }, + "it should be removed from object when using strictSchema true": function(res){ + assert.equal(res.target['not_here'], null); + assert.ok(res.valid); + } + }, "and if it has a missing non-required property": { topic: function (object, schema) { object = clone(object);