Skip to content

Instantly share code, notes, and snippets.

@patcullen
Created May 28, 2013 20:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patcullen/5665888 to your computer and use it in GitHub Desktop.
Save patcullen/5665888 to your computer and use it in GitHub Desktop.
A function to validate JSON objects against a schema.
// used in schema valiadtion for json objects
String.prototype.fromCamelToLabel = function() {
return this[0].toUpperCase() + this.substring(1).replace(/[A-Z]/g, function(h){
return " "+h;
});
};
var jv = {};
// Validate an object against a predefined schema.
jv.validate = function(object, schema) {
// if a label is specified then use it, otherwise use the property name
var getFieldLabel = function(o, f) {
if (typeof(o[f].label) == 'string') {
return o[f].label;
} else {
return f.fromCamelToLabel();
}
};
// this code is re-used after every type of check below
// no point in telling the user that they did not enter a string,..
// and then that their string is below minimum range, etc..
var errorsPresent = function(list) {
var t = { st: 'er', msg: list };
return t;
};
// check for null values
var r = [];
for (var n in schema)
if (((typeof object[n] === 'undefined') || (object[n] === null)) && (!schema[n]['null']))
r.push(getFieldLabel(schema, n) + ' cannot be null.');
if (r.length > 0) return errorsPresent(r);
// check data types
r = [];
for (var n in schema)
if ((typeof object[n] !== 'undefined') && (object[n] !== null))
if (schema[n].type != typeof(object[n]))
r.push(getFieldLabel(schema, n) + ' is the wrong data type.');
if (r.length > 0) return errorsPresent(r);
// check required fields are not blank, then also check fields against validations
// validation function for attributes
var valAttr = function(t, s) {
var r = [];
if ((typeof t !== 'undefined') && (t !== null)) {
if (s.type == 'string') {
if (t === '') {
if (s.req) r.push(getFieldLabel(schema, n) + ' is required.');
} else {
if (s.regex) if (t.search(s.regex) == -1)
r.push(getFieldLabel(schema, n) + ' is incorrectly formatted.');
if (s.min) if (t.length < s.min)
r.push(getFieldLabel(schema, n) + ' is too short.');
if (s.max) if (t.length > s.max)
r.push(getFieldLabel(schema, n) + ' is too long.');
}
}
if (s.type == 'number') {
if (s.min && (t < s.min))
r.push(getFieldLabel(schema, n) + ' is too small.');
if (s.max && (t > s.max))
r.push(getFieldLabel(schema, n) + ' is too big.');
}
if (s.type == 'object') {
if (typeof s.schema !== 'undefined') {
var y = jv.validate(t, s.schema);
if (y.st == 'er') y.msg.each(function(mi){r.push(mi);});
}
}
}
return r;
};
// now run through attributes and validate them with the above fn
r = [];
for (var n in schema) {
var t = object[n];
var s = schema[n];
if ((typeof t !== 'undefined') && (t !== null)) {
if (s.array) { // if is an array, then run validation on every element
for (i = 0; i<t.length && r.length==0; i++) {
var y = valAttr(t[i], s);
if (y.length!=0) y.each(function(mi){r.push(mi);});
}
} else {
var y = valAttr(t, s);
if (y.length!=0) y.each(function(mi){r.push(mi);});
}
}
}
if (r.length > 0) return errorsPresent(r);
// check custom functions
r = [];
for (var n in schema) {
var s = schema[n];
if (s.custom) {
var cr = s.custom(object[n], object);
if ((typeof cr !== 'undefined') && cr.length > 0)
r = r.concat(cr);
}
}
if (r.length > 0) return errorsPresent(r);
// wow, no errors thrown? then the object validates against the specified schema
return { st: 'ok' };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment