【问题标题】:Matching a string to one of many patterns and extracting data将字符串与多种模式之一匹配并提取数据
【发布时间】:2019-06-25 07:23:18
【问题描述】:

我有一个问题想用 RegEx 或任何其他方法(如果有更好的方法)来解决。我尝试了几种方法来实现目标,但都没有真正奏效。

我有一个带端点的数组:

const endpoints = [
    {
        id: 1,
        url: "/api/items/:itemId"
    },
    {
        id: 2,
        url: "/api/users/:userName/delete"
    },
    {
        id: 3,
        url: "/api/users/:userName/edit"
    }
];

还有一个请求网址:

const url = "/api/users/max/edit";

现在我想要的是有一个这样的函数:

const rewrite = (url, endpoints) => {

    // What is the best way to achieve the following return value:

    return {
        endpointId: 3,
        values: {
            userName: "max"
        }
    };
};

说明:该函数应该为 url 找到适当的端点。以冒号开头的端点 url 的所有部分都不是静态的,而是应该用请求 url 中的值替换。在这种情况下,:userName 应替换为 max

我从事网络开发已经有一段时间了,但说实话,我几乎不知道如何解决这样的问题。

【问题讨论】:

    标签: javascript regex url url-routing


    【解决方案1】:

    您可以通过endpoints 将每个.url 转换为正则表达式来测试网址。

    当找到匹配的时候,只需提取需要的部分并用属性名组成一个对象:

    <script>
        const myEndpoints = [
            {
                id: 1,
                url: "/api/items/:itemId"
            },
            {
                id: 2,
                url: "/api/users/:userName/delete"
            },
            {
                id: 3,
                url: "/api/users/:userName/edit"
            }
        ];
    
        const myUrl = "/api/users/nermal/edit";
    
        const rewrite = (url, endpoints) => {
    
            for (let i = 0; i < endpoints.length; i++) {
                var rep = new RegExp(":(\\w+)", "m");
                var propName = rep.exec(endpoints[i].url);
    
                var reu = new RegExp(endpoints[i].url.replace(propName[0], "(.*)"));
                var a = reu.exec(url);
    
                if (a !== null) {
                    var x = new Object;
                    x["endpointId"] = endpoints[i].id;
                    var y = new Object;
                    y[propName[1]] = a[1];
                    x["values"] = y;
                    return x;
                }
    
            }
    
            return null;
        };
    
        var q = rewrite(myUrl, myEndpoints);
        console.log(q);
        console.log(q.values);
    
    </script>
    

    输出:

    对象 { endpointId:3,值:{…} }
    对象{用户名:“nermal”}

    【讨论】:

    • 这正是我们所需要的。尽管我想指出,这只适用于 URL 中只有 1 个属性的情况。例如:模式/api/users/:userName/items/:itemId 不会捕获itemId
    • @Jack 同意。但至少 OP 可以从那里开发它。
    • 除了@Jack 指出的问题之外,如果有另一个端点的 URL /api/users/:userName/edit/more,这将不起作用。如果请求 URL 是/api/users/nermal/edit/more,该函数返回 id 为 3 的端点。我想如果你再解释一下代码,我可以找出解决方案。例如。 (.*) 到底是什么?
    • @Ruudy 该行是创建一个新的正则表达式,例如“/api/users/(.*)/delete”,以便从 url 中提取例如“nermal”。跨度>
    • @Ruudy 您可以使用regex101 之类的网站来获取正则表达式的解释。 (请记住,":(\\w+)" 实际上只有一个反斜杠,因为它需要在 JavaScript 字符串中进行转义。)
    【解决方案2】:
    const rewrite = (url, endpoints) => {
        var doubledArray = Array.prototype.map.call(endpoints, function(el) {
            return {
                id: el.id,
                url: el.url.split('/')
            };
        });
    
        var parts = url.split('/');
        var i = 0;
        parts.forEach(function(element) {
            doubledArray = doubledArray.filter(el => (element == el.url[i] || el.url[i].startsWith(':')));
            i++;
        });
    
        return {
            endpointId: doubledArray[0].id,
            values: {
                [`${doubledArray[0].url.filter(el => el.startsWith(':'))[0].substring(1)}`]: parts[doubledArray[0].url.findIndex(function (el) { return el.startsWith(':'); } )],
            }
        };
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 2018-11-03
      相关资源
      最近更新 更多