JavaScript 递归验证

标签 javascript json recursion tree

我想使用条件(AND、NOT、OR)和 id 键验证 json 树。类似这样的事情:

{

    "OR": [
        {
            "AND": [
                {
                    "NOT": [
                        {
                            "id": 2
                        }
                    ]
                },
                {
                    "id": 2
                }
            ]
        },
        {
            "AND": [
                {
                    "id": 3
                },
                {
                    "id": 3
                }
            ]
        }
    ]

}

这是有效的树。但如果 json 包含任何其他操作或有空([], {}),它将无效。例如,

{
    "X": [ //INVALID TAG
        {
            "AND": [
                {
                    "NOT": [
                        {
                            //EMPTY
                        }
                    ]
                },
                {
                    "id": 2
                }
            ]
        },
        {
            "AND": [
                {
                    "id": 3
                },
                {
                    "id": 3
                }
            ]
        }
    ]

}

我的代码:

var validateRule = function (js) {
console.log('current validation ' + JSON.stringify(js));

if (js.hasOwnProperty('OR')) {
    return js.hasOwnProperty('length') ? js.length > 0 && validateRule(js.OR) : validateRule(js.OR);
}

if (js.hasOwnProperty('AND')) {
    return js.hasOwnProperty('length') ? js.length > 0 && validateRule(js.AND) : validateRule(js.AND);
}

if (js.hasOwnProperty('NOT')) {
    return js.hasOwnProperty('length') ? js.length > 0 && validateRule(js.NOT) : validateRule(js.NOT);
}

if (js.hasOwnProperty('length')) { //JSON Array
    if (js.length == 0) {
        return false;
    } else if (js.length == 1) {
        return js[0].hasOwnProperty('id');
    } else {
        for (var key in js) {
            if (js.hasOwnProperty(key)) {
                return validateRule(js[key]);
            }
        }
    }
} else {
    return js.hasOwnProperty('id');
}
};

但是由于在循环中我的“返回”代码无法正常工作。请给我建议。

最佳答案

异常可能是在嵌套验证中传递失败的最干净的方法。例如,

function classOf(p) {
    return {}.toString.call(p).slice(8, -1);
}

function check(expr) {

    if(classOf(expr) != "Object")
        throw SyntaxError("Object expected");

    if(!Object.keys(expr).length)
        throw SyntaxError("Empty object");

    return Object.keys(expr).forEach(function(key) {
        var val = expr[key];
        switch(key) {
            case "AND":
            case "OR":
            case "NOT":
                if(classOf(val) != "Array")
                    throw SyntaxError("Array expected");
                if(key == "NOT" && val.length !== 1)
                    throw SyntaxError("Incorrect number of arguments");
                if(key != "NOT" && val.length < 2)
                    throw SyntaxError("Incorrect number of arguments");
                val.forEach(check);
                break;
            case "id":
                if(classOf(val) != "Number")
                    throw SyntaxError("Number expected");
                break;
            default:
                throw SyntaxError("Invalid operator " + key);
        }
    });
}

顶层代码会有点难看,但由于 JS 不支持类型化的 catch block ,这是不可避免的:

try {
    check(expr);
    // expression is valid, move on
} catch(e) {
    if(e instanceof SyntaxError)
       // expression is invalid, handle that
    else
       // something else went wrong
       throw e;
}

关于JavaScript 递归验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26866172/

相关文章:

java - 如何在Java中递归地获取树结构的所有叶子

java - JAVA中的递归字符串

javascript - 有没有办法防止在html中重复代码我正在使用bootstrap 4在一页中折叠20次

javascript - 在 JSON 源数据中使用 AngularJS 表达式

javascript - 如何使用 vanilla JS 在 JSON 对象中记录表单输入?

javascript - 如何使用事件驱动模型 "keep trying until it works"?

javascript - 如何以编程方式删除 <H1>~<H6> 标签?

javascript正则表达式分割不跨浏览器

javascript - 使用浏览器检测重定向到移动网站

javascript - 通过 json 和 ajax 将事件从 Controller 获取到完整日历