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?

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"];
9
  • 11
    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. Commented Jun 15, 2010 at 1:28
  • 6
    @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 ... Commented Oct 21, 2010 at 2:08
  • 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? Commented Dec 30, 2010 at 21:24
  • 2
    @RussBradberry You can't really have val=foo&val=bar&val=baz; it would have to be val[]=foo&val[]=bar&val[]=baz Commented Dec 8, 2011 at 21:18
  • 1
    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')) || '';
    – user24601
    Commented Jan 9, 2014 at 3:49
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"]
12
  • 8
    that isn't a single line - it's several lines formatted badly!
    – JonnyRaa
    Commented Jun 20, 2014 at 10:13
  • 2
    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]; } );`
    – Qwerty
    Commented Jun 20, 2014 at 11:11
  • 2
    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!
    – JonnyRaa
    Commented Jun 20, 2014 at 11:20
  • @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
    Commented Jan 9, 2015 at 15:08
  • 1
    @Qwerty, it's probably because your "one-liner" should be reformatted so that reading it doesn't require horizontal scrolling. I have adjusted it.
    – P i
    Commented Jul 24, 2015 at 15:31
11

Maybe http://plugins.jquery.com/query-object/?

This is the fork of it https://github.com/sousk/jquery.parsequery#readme.

6
  • 37
    This should be native to jquery
    – gcb
    Commented Apr 8, 2011 at 8:36
  • @EvanMulawski Thanks. The plug-in just disappeared it seems. I added a different link, which might help.
    – Shadow2531
    Commented Nov 30, 2011 at 0:58
  • The method provided by CMS is easier and cleaner. Esp. if you are not already using jquery.
    – jcoffland
    Commented Sep 5, 2012 at 0:09
  • 1
    You can refer this library to do that - github.com/Mikhus/jsurl
    – Mikhus
    Commented Apr 26, 2013 at 6:32
  • 1
    Here's the proper link: plugins.jquery.com/query-object
    – thexfactor
    Commented Feb 3, 2014 at 20:35
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

1
  • There is no just borrowing the code from Node,js, it's highly intertwingled.
    – alfwatt
    Commented Jul 25, 2014 at 21:32
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;
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 "";
}
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);
4
  • 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
    Commented Feb 17, 2014 at 11:00
  • @Rup, the update was made after this answer.
    – Qwerty
    Commented Jun 12, 2014 at 8:12
  • @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
    Commented Jun 12, 2014 at 9:40
  • @Rup Yup, sorry. And yup.
    – Qwerty
    Commented Jun 12, 2014 at 9:46
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>

1
  • Actually, I did remove the jQuery dependency in the code I gave in my answer ;-) Commented Mar 6, 2016 at 13:55
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.

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]);
        }
    }
}
3
  • You can also .toLowerCase() the name if you want hfname matching to be case-insensitive.
    – Shadow2531
    Commented Mar 15, 2009 at 5:03
  • 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.
    – Shadow2531
    Commented Mar 15, 2009 at 5:06
  • 1
    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.
    – Shadow2531
    Commented Mar 15, 2009 at 5:41
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'
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
2
  • Neat, but apart from the way you remove the leading ? that's basically the same as the two answers above you?
    – Rup
    Commented Aug 4, 2014 at 14:28
  • 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. Commented Aug 8, 2014 at 7:49
1

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

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. :)

3
  • 1
    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.
    – bobince
    Commented Mar 15, 2009 at 15:08
  • 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. :)
    – core
    Commented Mar 15, 2009 at 22:44
  • javascript isnt your native tongue what does it mean , you should learn it even if you need a library to use
    – Marwan
    Commented Nov 1, 2011 at 8:06
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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.