JavaScript查询字符串

106

是否有任何JavaScript库可以像ASP.NET一样将查询字符串转换成字典?

类似以下的用法:

var query = window.location.querystring["query"]?

在.NET领域之外,“查询字符串”是否被称为其他名称?为什么不将location.search拆分为“键/值集合”?

编辑:我已经编写了自己的函数,但是否有任何主要的JavaScript库可以执行此操作?


3
我可以翻译该网址的内容:http://medialize.github.com/URI.js/该网址提供了一个 URI.js 库,它是用于解析、操作和生成统一资源标识符(URI)的 JavaScript 库。这个库可以帮助开发者处理 URL 中的各种参数、片段、路径等元素,并轻松地构建自定义的 URI。 - deerchao
非常重复:https://dev59.com/nHNA5IYBdhLWcg3wmfAa和https://dev59.com/nHNA5IYBdhLWcg3wmfAa - DavidTaubmann
1
@davidtaubmann那个更老,它会是相反的。有趣的是,它们本质上是在问同样的问题,但由于问题的格式,一个得到了社区关注,而另一个则被关闭了。 - Andre Figueiredo
15个回答

232

您可以从location.search属性中提取键/值对,该属性包含跟随?符号的URL的一部分,包括?符号。

function getQueryString() {
  var result = {}, queryString = location.search.slice(1),
      re = /([^&=]+)=([^&]*)/g, m;

  while (m = re.exec(queryString)) {
    result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }

  return result;
}

// ...
var myParam = getQueryString()["myParam"];

11
这并不是胜利。如果一个键的值中有“=”字符怎么办?例如,dork.com/?equation=10=2。你可以说它应该进行URL编码,但确实没有必要这样做。我曾经犯过写一个类似于这样的天真函数的错误。这个函数考虑到了不止一个边缘情况。 - JamesBrownIsDead
6
@James,我忘了提到几个月前我修改了函数,现在它可以正确处理你的例子dork.com/?equation=10=2... - Christian C. Salvadó
2
@CMS 这并没有处理查询字符串中数组的可能性,例如 ?val=foo&val=bar&val=baz,你会如何适应这种情况? - Russ Bradberry
2
@RussBradberry 你不能真的有 val=foo&val=bar&val=baz;它必须是 val[]=foo&val[]=bar&val[]=baz - Brian Driscoll
1
当我的值中有空格,而我的变量最终以%20结尾时,我觉得它不完整。因此,我用result[keyValuePair[0]] = decodeURIComponent((keyValuePair[1]+'').replace(/\+/g, '%20')) || '';替换了result[keyValuePair[0]] = keyValuePair[1] || ''; - user24601
显示剩余4条评论

22

tl;dr使用原生JavaScript在一行(左右)代码中提供的解决方案

var queryDict = {}
location.search.substr(1).split("&").forEach(function(item) {
    queryDict[item.split("=")[0]] = item.split("=")[1]
})

对于查询字符串?a=1&b=2&c=3&d&e,它返回:

> queryDict
a: "1"
b: "2"
c: "3"
d: undefined
e: undefined

多值键编码字符

请参考原始答案:如何在JavaScript中获取查询字符串的值?

"?a=1&b=2&c=3&d&e&a=5&a=t%20e%20x%20t&e=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dståle%26car%3Dsaab"
> queryDict
a: ["1", "5", "t e x t"]
b: ["2"]
c: ["3"]
d: [undefined]
e: [undefined, "http://w3schools.com/my test.asp?name=ståle&car=saab"]

8
那不是一行文字 - 它是几行格式糟糕的文字! - JonnyRaa
2
该死,我不知道该说什么... 你抓住了我。这里有一个多行解决方案: var queryDict = {}; location.search.substr(1).split("&").forEach( function(item) { queryDict[item.split("=")[0]] = item.split("=")[1]; } ); - Qwerty
2
哈哈,我喜欢它!抱歉,我曾经和一个人一起工作,他经常说“我找到了一个可以做x的一行代码”,然后只会展示三行代码,而且没有换行! - JonnyRaa
1
@Qwerty,这可能是因为你的“一行代码”应该被重新格式化,以便阅读它时不需要水平滚动。我已经进行了调整。 - P i
如果您的查询中有编码字符,请导航到如何在JavaScript中获取查询字符串值?。那里有一个更复杂的解决方案。 - Qwerty
显示剩余7条评论

11

37
这应该是jQuery的本地功能。 - gcb
@EvanMulawski 谢谢。插件好像消失了。我加了一个不同的链接,可能有所帮助。 - Shadow2531
CMS提供的方法更加简单和清晰,尤其是如果您还没有使用jQuery的话。 - jcoffland
@jcoffland 我同意。我自己也使用类似的正则表达式来解析mailto URI。 - Shadow2531
1
你可以参考这个库来实现 - https://github.com/Mikhus/jsurl - Mikhus
1
这是正确的链接:http://plugins.jquery.com/query-object/ - thexfactor

8
在找到这篇文章后,我认为我应该补充说明最受赞同的解决方案并不是最好的。它不能处理数组值(例如?a=foo&a=bar——在这种情况下,我期望得到a返回['foo','bar'])。据我所知,它也没有考虑编码值,比如十六进制字符编码,其中%20代表空格(例如:?a=Hello%20World),或者加号用于表示空格(例如:?a=Hello+World)。
Node.js提供了一个看起来非常完整的查询字符串解析解决方案。因为它相当孤立且具备宽松许可证,因此很容易从中提取并在自己的项目中使用。
它的代码可以在此处查看:https://github.com/joyent/node/blob/master/lib/querystring.js Node的测试可以在此处查看:https://github.com/joyent/node/blob/master/test/simple/test-querystring.js 我建议尝试使用一些流行答案中的一些测试,看看它们如何处理。
还有一个项目,我曾参与其中,专门添加了此功能。它是Python标准库查询字符串解析模块的端口。我的fork可以在此处找到:https://github.com/d0ugal/jquery.qeeree

不能只是从Node.js中借用代码,因为它们高度交织在一起。 - alfwatt

6
你可以使用库sugar.js。从sugarjs.com网站获取以下信息:

Object.fromQueryString ( str , deep = true )

Converts the query string of a URL into an object. If deep is false, conversion will only accept shallow params (ie. no object or arrays with [] syntax) as these are not universally supported.

Object.fromQueryString('foo=bar&broken=wear') >{"foo":"bar","broken":"wear"}
Object.fromQueryString('foo[]=1&foo[]=2') >{"foo":[1,2]}

例子:

var queryString = Object.fromQueryString(location.search);
var foo = queryString.foo;

3
如果您手头已有查询字符串,请使用以下方式:
 /**
 * @param qry the querystring
 * @param name name of parameter
 * @returns the parameter specified by name
 * @author eduardo.medeirospereira@gmail.com
 */

function getQueryStringParameter(qry,name){
    if(typeof qry !== undefined && qry !== ""){
        var keyValueArray = qry.split("&");
        for ( var i = 0; i < keyValueArray.length; i++) {
            if(keyValueArray[i].indexOf(name)>-1){
                return keyValueArray[i].split("=")[1];
            }
        }
    }
    return "";
}

2

代码

Eldon McGuinness的这个Gist是我目前看到的最完整的JavaScript查询字符串解析器实现。

不幸的是,它是作为jQuery插件编写的。

我将它重写为纯JS,并进行了一些改进:

function parseQuery(str) {
  var qso = {};
  var qs = (str || document.location.search);
  // Check for an empty querystring
  if (qs == "") {
    return qso;
  }
  // Normalize the querystring
  qs = qs.replace(/(^\?)/, '').replace(/;/g, '&');
  while (qs.indexOf("&&") != -1) {
    qs = qs.replace(/&&/g, '&');
  }
  qs = qs.replace(/([\&]+$)/, '');
  // Break the querystring into parts
  qs = qs.split("&");
  // Build the querystring object
  for (var i = 0; i < qs.length; i++) {
    var qi = qs[i].split("=");
    qi = qi.map(function(n) {
      return decodeURIComponent(n)
    });
    if (typeof qi[1] === "undefined") {
      qi[1] = null;
    }
    if (typeof qso[qi[0]] !== "undefined") {

      // If a key already exists then make this an object
      if (typeof (qso[qi[0]]) == "string") {
        var temp = qso[qi[0]];
        if (qi[1] == "") {
          qi[1] = null;
        }
        qso[qi[0]] = [];
        qso[qi[0]].push(temp);
        qso[qi[0]].push(qi[1]);

      } else if (typeof (qso[qi[0]]) == "object") {
        if (qi[1] == "") {
          qi[1] = null;
        }
        qso[qi[0]].push(qi[1]);
      }
    } else {
      // If no key exists just set it as a string
      if (qi[1] == "") {
        qi[1] = null;
      }
      qso[qi[0]] = qi[1];
    }
  }
  return qso;
}

如何使用

var results = parseQuery("?foo=bar&foo=boo&roo=bar;bee=bop;=ghost;=ghost2;&;checkbox%5B%5D=b1;checkbox%5B%5D=b2;dd=;http=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab&http=http%3A%2F%2Fw3schools2.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab");

输出

{
  "foo": ["bar", "boo" ],
  "roo": "bar",
  "bee": "bop",
  "": ["ghost", "ghost2"],
  "checkbox[]": ["b1", "b2"],
  "dd": null,
  "http": [
    "http://w3schools.com/my test.asp?name=ståle&car=saab",
    "http://w3schools2.com/my test.asp?name=ståle&car=saab"
  ]
}

另请参阅此Fiddle


2
// How about this
function queryString(qs) {
    var queryStr = qs.substr(1).split("&"),obj={};
    for(var i=0; i < queryStr.length;i++)
        obj[queryStr[i].split("=")[0]] = queryStr[i].split("=")[1];
    return obj;
}

// Usage:
var result = queryString(location.search);

这与上面最高票答案中的“更新:无需使用正则表达式”代码基本相同。在此问题中还有许多类似的代码。你至少需要在提取的字符串上使用 decodeURIComponent - Rup
@Rup,在此回答之后进行了更新。 - Qwerty
@Qwerty 不是这样的:更新是在2013年2月,而这个答案几乎是一年后的2014年2月。但是谁在乎呢,有很多类似的代码在飞来飞去。不过,我的decodeURIComponent的评论还是适用的。 - Rup
@Rup 嗯,抱歉。没错。 - Qwerty

2
值得注意的是,John Slegers提到的那个库确实有一个jQuery依赖项,但这里有一个纯JavaScript版本。

https://github.com/EldonMcGuinness/querystring.js

我本来想在他的帖子上发表评论,但是我没有足够的声望去这样做。:/

例子:

下面的例子处理以下虽然不规则但是查询字符串:

?foo=bar&foo=boo&roo=bar;bee=bop;=ghost;=ghost2;&;checkbox%5B%5D=b1;checkbox%5B%5D=b2;dd=;http=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab&http=http%3A%2F%2Fw3schools2.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab 

var qs = "?foo=bar&foo=boo&roo=bar;bee=bop;=ghost;=ghost2;&;checkbox%5B%5D=b1;checkbox%5B%5D=b2;dd=;http=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab&http=http%3A%2F%2Fw3schools2.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab";
//var qs = "?=&=";
//var qs = ""

var results = querystring(qs);

(document.getElementById("results")).innerHTML =JSON.stringify(results, null, 2);
<script 
src="https://rawgit.com/EldonMcGuinness/querystring.js/master/dist/querystring.min.js"></script>
<pre id="results">RESULTS: Waiting...</pre>


实际上,我在我的答案中已经删除了jQuery依赖;-) - John Slegers

1

function decode(s) {
    try {
        return decodeURIComponent(s).replace(/\r\n|\r|\n/g, "\r\n");
    } catch (e) {
        return "";
    }
}
function getQueryString(win) {
    var qs = win.location.search;
    var multimap = {};
    if (qs.length > 1) {
        qs = qs.substr(1);
        qs.replace(/([^=&]+)=([^&]*)/g, function(match, hfname, hfvalue) {
            var name = decode(hfname);
            var value = decode(hfvalue);
            if (name.length > 0) {
                if (!multimap.hasOwnProperty(name)) {
                    multimap[name] = [];
                }
                multimap[name].push(value);
            }
        });
    }
    return multimap;
}
var keys = getQueryString(window);
for (var i in keys) {
    if (keys.hasOwnProperty(i)) {
        for (var z = 0; z < keys[i].length; ++z) {
            alert(i + ":" + keys[i][z]);
        }
    }
}

如果您希望hfname匹配不区分大小写,您还可以使用.toLowerCase()函数将名称转换为小写。 - Shadow2531
您还可以检查值是否为空。如果是,则可以跳过添加条目,以便数组仅包含非空值。 - Shadow2531
1
unescape() 不支持 UTF-8 序列,因此您可能需要使用 decodeURIComponent()。但是如果您想要将 + 字符解码为空格,请在解码之前对字符串运行 .replace(/+/g, " ")。 - Shadow2531

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接