index.js
function validateObjectEntity(modelObject, entity, parents, errors) {
  if (!errors) errors = {};
  if (!errors.text) errors.text = [];
  if (!parents) parents = [];

  for (var key in entity) {
    var fieldName = parents + '.' + key;
    if (!modelObject || !modelObject[key]) {
      if (!errors.notRequired) errors.notRequired = [];
      errors.notRequired.push(fieldName);
      errors.text.push('Field ' + fieldName + ' not required');
    } else if (!modelObject[key].type) {
      validateObjectEntity(modelObject[key], entity[key], [parents, key], errors);
    } else if (!modelObject[key].check(entity[key])) {
      if (!errors.notMatched) errors.notMatched = {};
      errors.notMatched[fieldName] = modelObject[key].type;
      errors.text.push('Field ' + fieldName + ' not matched with type ' + modelObject[key].type);
    }
  }

  return errors;
}
function validateObjectEntity(modelObject, entity, parents, errors) {
  if (!errors) errors = {};
  if (!errors.text) errors.text = [];
  if (!parents) parents = [];

  for (var key in entity) {
    var fieldName = parents + '.' + key;
    if (!modelObject || !modelObject[key]) {
      if (!errors.notRequired) errors.notRequired = [];
      errors.notRequired.push(fieldName);
      errors.text.push('Field ' + fieldName + ' not required');
    } else if (!modelObject[key].type) {
      validateObjectEntity(modelObject[key], entity[key], [parents, key], errors);
    } else if (!modelObject[key].check(entity[key])) {
      if (!errors.notMatched) errors.notMatched = {};
      errors.notMatched[fieldName] = modelObject[key].type;
      errors.text.push('Field ' + fieldName + ' not matched with type ' + modelObject[key].type);
    }
  }

  return errors;
}
check for extra fields and match recursively