Reputation: 931
What is the best way to test the integrity of a complex object in JavaScript?
My object has a bunch of different variables, some optional, some required. The correct structure is vital to the code's functionality, but if I make a mistake during the definition, finding the exact value that caused the problem could get very tedious. Especially with error messages that tell me no more than "Somwehere in the code you're using the wrong variable type!".
My object could look something like this, for example:
{
name:"Test",
categories:{
A:{
depth:1,
groups:{
main:[
{myFunction:funcA, arg:[1,2]},
{myFunction:funcB}
]
}
},
B:{
groups{
main:[
{myFunction:funcC}
],
secondary:[
{myFunction:funcD}
]
}
}
}
}
Thanks!
Upvotes: 1
Views: 1130
Reputation: 931
Okay, this is how I've solved it: I create an object that defines what my complex objects should look like. A blueprint, in a way.
var structure = {
property1: {id:"name", type:"string", required:false},
property2: {
id:"categories", type:"object", required:true,
content:{
property1:{
type:"object", min:1,
content:{
property1:{id:"depth", type:"positiveinteger", required:false},
property2:{
id:"groups", type:"object", required:true,
content:{
property1:{
type:"array", min:1,
content:{
type:"object", min:1,
content:{
property1:{id:"myFunction", type:"function", required:true},
property2:{id:"args", type:"array", required:false},
}
}
}
}
}
}
}
}
}
}
Then I run a function that compares the blueprint ("struct") with the object to be tested ("def"):
function compareStructure(struct, def){
if(isArray(def)){
if(isDefined(struct.min) && def.length < struct.min){ alert("Error in structur check: " + " min is " + struct.min + "."); return false}
if(isDefined(struct.max) && def.length > struct.max){ alert("Error in structur check: " + " max is " + struct.max + "."); return false}
for(var i = 0; i < def.length; i++){
compareStructure(struct.content, def[i]);
}
} else {
for(var k in struct){
if(struct[k].id){
propFound = false;
for(var m in def) if(m == struct[k].id) propFound = m;
if(!propFound && struct[k].required){ alert("Error in structure check: " + struct[k].id + " not defined."); return false}
if(propFound && !verifyThis(struct[k], def[propFound], propFound)) return false;
if(propFound && struct[k].content) compareStructure(struct[k].content, def[propFound]);
} else {
for(var m in def){
if(!verifyThis(struct[k], def[m], m)) return false;
if(struct[k].content) compareStructure(struct[k].content, def[m]);
}
}
}
}
}
function verifyThis(struct, def, prop){
// This is where the checks for types and values are made.
}
The comparison function is still work in progress, but that's the concept I'm going with for now.
Upvotes: 0
Reputation: 359966
There isn't a good way to do this beyond writing a function that receives an object as input, and verifies that it has the "right" structure.
function isValid(obj)
{
if (!o) return false;
if (typeof o.name !== 'string') return false;
if (typeof o.categories !== 'object') return false;
if (typeof o.categories.a !== 'object') return false;
if (typeof o.categories.b !== 'object') return false;
// etc...
return true;
}
On the other hand, you can define a constructor which takes whatever arguments you need to construct the object properly.
function MyObj(name, categoryNames /* other args */)
{
this.name = name;
this.categories = {};
for (var i=0; i<categoryNames.length; i++)
{
this.categories[categoryNames[i]] =
{
groups: {main: []}
};
}
// etc
}
// use it like this:
var foo = new MyObj('Test', ['A', 'B'] /* other args */);
Upvotes: 4
Reputation: 11625
You might be try JSON Schema Validation. You might need some modifications to account for the fact that you can have functions as well which are not valid in JSON.
Upvotes: -1
Reputation: 25164
You can try to validate your object against a JSON Schema
But this may be an overkill.
Upvotes: -1