1
\$\begingroup\$

For my latest app I wanted to be able to code the front-end first, without having to do super extensive documentation and without forgetting my data types later on while coding the back-end. I thus tried to make some kind of JSON Validator that expects something and outputs true or false depending on the input fed to it. (Meaning that I can define my data structures that way)

What I have works, but I'm not sure if that was the right way to go. Any comments?

export class ArrayValidator {

/**
 * Array-Template Syntax:
 * {
 *      "layer_type": "object"|"array"|"value",
        (if array):
        "items": -1,
        "item": {"layer_type": ...}
        (end if array)
        (if value)
        "value": 'regexp'
        (end if value)
        (if object)
        "properties": [
            {
                "name": "string",
                "null_allowed": true|false,
                "value": {"layer_type": etc ...}
            },
            {...}
        ]
        (end if object)
 *  }
**/
public static testUpon(arrayToTest, arrayTemplate) : boolean {
    if(arrayTemplate.layer_type == "object"){
        for(let prop of arrayTemplate.properties){
            if(arrayToTest[prop.name] == null && prop.nullAllowed == 'false'){
                console.log("[ArrayValidator][Error]Nonexistent property: " + prop.name);
                return false;
            }
            if(arrayToTest[prop.name] != null && !ArrayValidator.testUpon(arrayToTest[prop.name], prop.value)) return false;
        }
    }else if(arrayTemplate.layer_type == "array"){
        if(arrayTemplate.items!=-1 && arrayToTest.length != arrayTemplate.items){
            console.log("[ArrayValidator][Error]Array of wrong length.");
            return false;
        }
        for(let item of arrayToTest){
            if(!ArrayValidator.testUpon(item, arrayTemplate.item)) return false;
        }
    }else if(arrayTemplate.layer_type == "value"){
        let regexp = new RegExp(arrayTemplate.value);
        let res = regexp.test(arrayToTest);
        if(!res) console.log("[ArrayValidator][Error]Value Regexp doesn't match. [Regexp: " + arrayTemplate.value + ", Value: " + arrayToTest + "]");
        return res;
    }
    return true;
}

public static test(){
    let template = JSON.parse('{"layer_type": "object", "properties": [{"name": "obj", "nullAllowed": "false", "value": {"layer_type": "object", "properties": []}}, {"name": "embed", "nullAllowed": "false", "value": {"layer_type": "array", "items": -1, "item":{"layer_type": "value", "value": "(.+?)"}}}, {"name": "testVal", "nullAllowed": "false", "value": {"layer_type": "value", "value": "^[A-Za-z]+$"}}]}');
    let test = JSON.parse('{"testVal": "Hello", "embed": ["test", "another test", 24], "obj": {}}');
    console.log("Output: " + ArrayValidator.testUpon(test, template));
}
}
\$\endgroup\$
1
\$\begingroup\$

In other words, you're trying to validate that the parsed JSON matches the data structure you're expecting :)

I recommend creating a JSON Schema, updating it as you develop your front-end, and using a Schema Validator library to validate that the object you're creating is consistent with the schema.

This way, the schema will serve both as API documentation and as your test.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.