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);