验证查询参数并使用正则表达式进行解析。

问题描述 投票:0回答:1

我是新手,请教一下,如何用下面所有的组合来取一个查询参数。

(ParamName=Operator:ParamValue)是我的一组查询参数值。这将用;(AND)或,(OR)分开,我想把它们放在括号里。就像下面的例子

例如 http:/,host:port>get?search=(date=gt:2020-02-06T00:00:00.000Z;(name=eq:Test,department=co:Prod))这里的日期要大于2020-02-06,name=。测试 或部门包含 产品.如何解析这些查询参数。请提出建议。

谢谢,Vijay

regex query-parameters
1个回答
0
投票

所以,我用JavaScript写了一个解决方案,但在其他语言中应该也能适应,只要稍加研究。

它的代码挺多的,但是你要实现的东西并不是超级容易的!

所以这里是代码,它被彻底的注释了,但是如果你有什么不明白的地方,请问吧,我很乐意回答你:)

//
// The 2 first regexes are a parameter, which looks like date=gt:2020-02-06T00:00:00.000Z for example.
// The difference between those 2 is that the 1st one has **named capture group**
//      For example '(?<operator>...)' is a capture group named 'operator'.
//      This will come in handy in the code, to keep things clean
//
const RX_NAMED_PARAMETER = /(?:(?<param>\w+)=(?<operator>\w+):(?<value>[\w-:.]+))/
const parameter = "((\\w+)=(\\w+):([\\w-:.]+)|(true|false))"

//
// The 3rd parameter is an operation between 2 parameters
//
const RX_OPERATION = new RegExp(`\\((?<param1>${parameter})(?:(?<and_or>[,;])(?<param2>${parameter}))?\\)`, '');
//                                   '---------.---------'  '-------.------'  '----------.---------' 
//                                       1st parameter          AND or OR          2nd parameter


my_data = {
    date: new Date(2000, 01, 01),
    name: 'Joey',
    department: 'Production'
}


/**
 * This function compates the 2 elements, and returns the bigger one.
 * The elements might be dates, numbers, or anything that can be compared.
 * The elements **need** to be of the same type
 */
function isGreaterThan(elem1, elem2) {
    if (elem1 instanceof Date) {
        const date = new Date(elem2).getTime();
        if (isNaN(date))
            throw new Error(`${elem2} - Not a valid date`);

        return elem1.getTime() > date;
    }
    if (typeof elem1 === 'number') {
        const num = Number(elem2);
        if (isNaN(num))
            throw new Error(`${elem2} - Not a number`);

        return elem1 > num;
    }
    return elem1 > elem2;
}

/**
 * Makes an operation as you defined them in your
 * post, you might want to change that to suit your needs
 */
function operate(param, operator, value) {
    if (!(param in my_data))
        throw new Error(`${param} - Invalid parameter!`);

    switch (operator) {
        case 'eq':
            return my_data[param] == value;
        case 'co':
            return my_data[param].includes(value);
        case 'lt':
            return isGreaterThan(my_data[param], value);
        case 'gt':
            return !isGreaterThan(my_data[param], value);
        default:
            throw new Error(`${operator} - Unsupported operation`);
    }
}

/**
 * This parses the URL, and returns a boolean
 */
function parseUri(uri) {

    let finalResult;

    // As long as there are operations (of the form <param1><; or ,><param2>) on the URL
    while (RX_OPERATION.test(uri)) {

        // We replace the 1st operation by the result of this operation ("true" or "false")
        uri = uri.replace(RX_OPERATION, rawOperation => {

            // As long as there are parameters in the operations (e.g. "name=eq:Bob")
            while (RX_NAMED_PARAMETER.test(rawOperation)) {

                // We replace the 1st parameter by its value ("true" or "false")
                rawOperation = rawOperation.replace(RX_NAMED_PARAMETER, rawParameter => {
                    const res = RX_NAMED_PARAMETER.exec(rawParameter);

                    return '' + operate(
                        res.groups.param,
                        res.groups.operator,
                        res.groups.value,
                    );
                    // The "res.groups.xxx" syntax is allowed by the
                    // usage of capture groups. See the top of the file.
                });
            }
            
            // At this point, the rawOperation should look like
            // (true,false) or (false;false) for example

            const res = RX_OPERATION.exec(rawOperation);

            let operation;
            if (res.groups.param2 === undefined)
                operation = res.groups.param1; // In case this is an isolated operation
            else
                operation = res.groups.param1 + ({',': ' || ', ';': ' && '}[res.groups.and_or]) + res.groups.param2;

            finalResult = eval(operation);
            return '' + finalResult;
        });
    }

    return finalResult;
}

let res;

res = parseUri("http://,host:port>/get?search=(date=gt:2020-02-06T00:00:00.000Z;(name=eq:Test,department=co:Prod))");
console.log(res);

res = parseUri("http://,host:port>/get?search=(date=lt:2020-02-06T00:00:00.000Z)");
console.log(res);
© www.soinside.com 2019 - 2024. All rights reserved.