106

Is there any JavaScript library that makes a dictionary out of the query string, ASP.NET style?

Something which can be used like:

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

Is "query string" called something else outside the .NET realm? Why isn't location.search broken into a key/value collection ?

EDIT: I have written my own function, but does any major JavaScript library do this?

Sachin Jain
21.9k34 gold badges113 silver badges177 bronze badges
asked Mar 15, 2009 at 3:50
4

15 Answers 15

231

You can extract the key/value pairs from the location.search property, this property has the part of the URL that follows the ? symbol, including the ? symbol.

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"];
Qwerty
32.4k25 gold badges130 silver badges158 bronze badges
answered Mar 15, 2009 at 4:08

9 Comments

This is not a win. What if a key's value has the '=' character in it? E.g. dork.com/?equation=10=2. You could argue it SHOULD be URL-encoded but it sure doesn't have to be. I made the mistake of writing a naive function like this myself once. There are more than one edge case this function account for.
@James, forgot to mention that a couple of months ago I've modified the function, now it correctly can handle your example dork.com/?equation=10=2 ...
@CMS this doesn't handle the possibility of an array in a query string that is represented as such ?val=foo&val=bar&val=baz how would you accomodate this?
@RussBradberry You can't really have val=foo&val=bar&val=baz; it would have to be val[]=foo&val[]=bar&val[]=baz
It seemed incomplete to me when my values had spaces and my vars ended up with %20's, so I replaced result[keyValuePair[0]] = keyValuePair[1] || ''; with result[keyValuePair[0]] = decodeURIComponent((keyValuePair[1]+'').replace(/\+/g, '%20')) || '';
|
22

tl;dr solution on a single(ish) line of code using vanilla javascript

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

For querystring ?a=1&b=2&c=3&d&eit returns:

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

multi-valued keys and encoded characters?

See the original answer at How can I get query string values in 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"]
answered Jan 16, 2014 at 16:23

12 Comments

that isn't a single line - it's several lines formatted badly!
Damn, I don't know what to say... You got me. Here, have some multilined solution: ` var queryDict = {}; location.search.substr(1).split("&").forEach( function(item) { queryDict[item.split("=")[0]] = item.split("=")[1]; } );`
haha I love it! Sorry I used to work with someone who used to say 'I've found a one liner that does x' and then just show you 3 lines with the line breaks taken out!
@JonnyLeeds No problem, I know exactly what you mean, but then, why would one write each of chained commands on new line? Then there is a function given as parameter (parameters are usually inlined) which has only a single assignment. It screams to be inlined! :D
@Qwerty, it's probably because your "one-liner" should be reformatted so that reading it doesn't require horizontal scrolling. I have adjusted it.
|
11
driconmax
9421 gold badge19 silver badges32 bronze badges
answered Mar 15, 2009 at 5:33

6 Comments

This should be native to jquery
@EvanMulawski Thanks. The plug-in just disappeared it seems. I added a different link, which might help.
The method provided by CMS is easier and cleaner. Esp. if you are not already using jquery.
You can refer this library to do that - github.com/Mikhus/jsurl
Here's the proper link: plugins.jquery.com/query-object
|
8

After finding this post, when looking myself I thought I should add that I don't think the most up-voted solution is the best. It doesn't handle array values (such as ?a=foo&a=bar - in this case I would expect getting a to return ['foo', 'bar']). It also as far as I can tell doesn't take into account encoded values - such as hex character encoding where %20 represents a space (example: ?a=Hello%20World) or the plus symbol being used to represent a space (example: ?a=Hello+World).

Node.js offers what looks like a very complete solutions to querystring parsing. It would be easy to take out and use in your own project as its fairly well isolated and under a permissive licence.

The code for it can be viewed here: https://github.com/joyent/node/blob/master/lib/querystring.js

The tests that Node has can be seen here: https://github.com/joyent/node/blob/master/test/simple/test-querystring.js I would suggest trying some of these with the popular answer to see how it handles them.

There is also a project that I was involved in to specifically add this functionality. It is a port of the Python standard lib query string parsing module. My fork can be found here: https://github.com/d0ugal/jquery.qeeree

answered Nov 20, 2011 at 17:50

1 Comment

There is no just borrowing the code from Node,js, it's highly intertwingled.
6

Or you could use the library sugar.js.

From 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]}

Example:

var queryString = Object.fromQueryString(location.search);
var foo = queryString.foo;
answered Aug 21, 2013 at 12:23

Comments

3

If you have the querystring on hand, use this:

 /**
 * @param qry the querystring
 * @param name name of parameter
 * @returns the parameter specified by name
 * @author [email protected]
 */
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 "";
}
answered May 3, 2012 at 18:48

Comments

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);
answered Feb 16, 2014 at 17:46

4 Comments

That's more-or-less the same as the "Update: no need to use regex" code in the highest-voted answer above. There's also loads of similar code in this question). You're missing decodeURIComponent on the extracted strings at least.
@Rup, the update was made after this answer.
@Qwerty No it wasn't: the update was Feb 2013 whereas this answer was nearly a year later in Feb 2014. But who cares, there's plenty of similar code flying about. My comments about the decodeURIComponent stand, though.
@Rup Yup, sorry. And yup.
2

It is worth noting, the library that John Slegers mentioned does have a jQuery dependency, however here is a version that is vanilla Javascript.

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

I would have simply commented on his post, but I lack the reputation to do so. :/

Example:

The example below process the following, albeit irregular, query string:

?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>

answered Feb 21, 2016 at 21:53

1 Comment

Actually, I did remove the jQuery dependency in the code I gave in my answer ;-)
2

The code

This Gist by Eldon McGuinness is by far the most complete implementation of a JavaScript query string parser that I've seen so far.

Unfortunately, it's written as a jQuery plugin.

I rewrote it to vanilla JS and made a few improvements :

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;
}

How to use it

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");

Output

{
 "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"
 ]
}

See also this Fiddle.

answered Feb 21, 2016 at 17:29

Comments

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]);
 }
 }
}
answered Mar 15, 2009 at 5:02

3 Comments

You can also .toLowerCase() the name if you want hfname matching to be case-insensitive.
You can also check to see if the value is empty or not. If it is, you can skip adding the entry so the array only contains non-empty values.
unescape() doesn't handle UTF-8 sequences, so you might want to use decodeURIComponent(). However then, if you want + chars to be decoded to spaces, run .replace(/\+/g, " ") on the string before decoding.
1

I like to keep it simple, readable and small.

function searchToObject(search) {
 var pairs = search.substring(1).split("&"),
 obj = {}, pair;
 for (var i in pairs) {
 if (pairs[i] === "") continue;
 pair = pairs[i].split("=");
 obj[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
 }
 return obj;
}
searchToObject(location.search);

Example:

searchToObject('?query=myvalue')['query']; // spits out: 'myvalue'
answered Jun 12, 2014 at 8:20

Comments

1

Function I wrote for a requirement similar to this with pure javascript string manipulation

"http://www.google.lk/?Name=John&Age=20&Gender=Male"
function queryize(sampleurl){
 var tokens = url.split('?')[1].split('&');
 var result = {};
 for(var i=0; i<tokens.length; i++){
 result[tokens[i].split('=')[0]] = tokens[i].split('=')[1];
 }
 return result;
}

Usage:

queryize(window.location.href)['Name'] //returns John
queryize(window.location.href)['Age'] //returns 20
queryize(window.location.href)['Gender'] //returns Male
answered Jul 31, 2014 at 15:16

2 Comments

Neat, but apart from the way you remove the leading ? that's basically the same as the two answers above you?
Just a small improvement. The way the method is used makes it easy for the user. User only needs to know what query string value he needs.
1

If you are using lodash + ES6, here is a one line solution: _.object(window.location.search.replace(/(^\?)/, '').split('&').map(keyVal => keyVal.split('=')));

answered Dec 10, 2015 at 21:34

Comments

0

Okay, since everyone is ignoring my actual question, heh, I'll post mine too! Here's what I have:

location.querystring = (function() {
 // The return is a collection of key/value pairs
 var queryStringDictionary = {};
 // Gets the query string, starts with '?'
 var querystring = unescape(location.search);
 // document.location.search is empty if no query string
 if (!querystring) {
 return {};
 }
 // Remove the '?' via substring(1)
 querystring = querystring.substring(1);
 // '&' seperates key/value pairs
 var pairs = querystring.split("&");
 // Load the key/values of the return collection
 for (var i = 0; i < pairs.length; i++) {
 var keyValuePair = pairs[i].split("=");
 queryStringDictionary[keyValuePair[0]] = keyValuePair[1];
 }
 // Return the key/value pairs concatenated
 queryStringDictionary.toString = function() {
 if (queryStringDictionary.length == 0) {
 return "";
 }
 var toString = "?";
 for (var key in queryStringDictionary) {
 toString += key + "=" + queryStringDictionary[key];
 }
 return toString;
 };
 // Return the key/value dictionary
 return queryStringDictionary;
})();

And the tests:

alert(window.location.querystring.toString());
for (var key in location.querystring) {
 alert(key + "=" + location.querystring[key]);
}

Mind you thought, JavaScript isn't my native tongue.

Anyway, I'm looking for a JavaScript library (e.g. jQuery, Prototype) that already has one written. :)

answered Mar 15, 2009 at 4:14

3 Comments

I'm not convinced you really need a library to do what amounts to three lines of code above! Still, at least you would hope a library would remember the decodeURIComponent() both the key and value, something every code snippet posted so far has failed to do.
You don't need a library. I wanted to compare my implementation to one in a library so I could see if I was missing any edge cases. :)
javascript isnt your native tongue what does it mean , you should learn it even if you need a library to use
0

Building on the answer by @CMS I have the following (in CoffeeScript which can easily be converted to JavaScript):

String::to_query = ->
 [result, re, d] = [{}, /([^&=]+)=([^&]*)/g, decodeURIComponent]
 while match = re.exec(if @.match /^\?/ then @.substring(1) else @)
 result[d(match[1])] = d match[2] 
 result

You can easily grab what you need with:

location.search.to_query()['my_param']

The win here is an object-oriented interface (instead of functional) and it can be done on any string (not just location.search).

If you are already using a JavaScript library this function make already exist. For example here is Prototype's version

answered Oct 17, 2012 at 19:16

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.