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,353
  • 33
  • 103
  • 168
core
  • 32,451
  • 45
  • 138
  • 193
  • 3
    found this: http://medialize.github.com/URI.js/ – deerchao Feb 09 '12 at 05:43
  • See also [How can I get query string values?](http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values) – Bergi Aug 01 '13 at 00:21
  • Very duplicated: http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript and http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript – DavidTaubmann Mar 22 '17 at 11:13
  • 1
    @davidtaubmann that one is older, it would be inverse. Funny that they essentially ask the same, but due to the format of the question one got the glory turned into community's, and other closed as off-topic. – Andre Figueiredo Mar 07 '18 at 20:26

15 Answers15

232

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
  • 29,062
  • 22
  • 108
  • 136
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 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. – JamesBrownIsDead Jun 15 '10 at 01: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` ... – Christian C. Salvadó Oct 21 '10 at 02: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? – Russ Bradberry Dec 30 '10 at 21:24
  • i just realized this is a very old post, but here is a possible solution: http://pastie.org/1418228 – Russ Bradberry Dec 30 '10 at 21:34
  • 2
    @RussBradberry You can't really have `val=foo&val=bar&val=baz`; it would have to be `val[]=foo&val[]=bar&val[]=baz` – Brian Driscoll Dec 08 '11 at 21:18
  • How do I get the same result in Ajax ? – Smit Aug 31 '12 at 12:55
  • I think your first one is better but awesomeness in either case. – King Friday Sep 12 '13 at 14:46
  • 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 Jan 09 '14 at 03:49
  • @CMS you should convert the expression inside the while loop to a boolean: `while (!!(m = re.exec(queryString))) {` so it can pass jsHint. – pizza247 Jul 08 '14 at 18:48
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"]
Community
  • 1
  • 1
Qwerty
  • 29,062
  • 22
  • 108
  • 136
  • 8
    that isn't a single line - it's several lines formatted badly! – JonnyRaa Jun 20 '14 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 Jun 20 '14 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 Jun 20 '14 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 Jan 09 '15 at 15:08
  • So, I've just received first downvote after a 14 upvote streak. Dear downvoter, mind shedding some light on it? :) – Qwerty Jan 09 '15 at 15:09
  • 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 Jul 24 '15 at 15:31
  • This doesn't produce the results you've documented. `queryDict.a == 't%20e%20x%20t'` – roydukkey Nov 23 '15 at 14:16
  • @roydukkey If you have _encoded characters_ in your query, you should navigate to [How can I get query string values in JavaScript?](http://stackoverflow.com/a/21152762/985454) There is a more complex solution. – Qwerty Nov 23 '15 at 17:05
  • @Qwerty My concern is that it doesn't create a array of value as suggested. ie. `["1", "5", "t e x t"]` – roydukkey Nov 23 '15 at 20:32
  • @roydukkey Yes, because for that you would have to follow the link provided, as the solution, which handles _multi-valued keys_ and _encoded characters_ is there and is more complex than the one above, which was tailored and simplified to fit the question. – Qwerty Nov 23 '15 at 20:34
  • Aw ic. That's not very clear I guess. – roydukkey Nov 24 '15 at 02:19
  • Thanks - this works wonderfully in Google Tag Manager. – turtlepower Sep 11 '19 at 22:27
11

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

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

driconmax
  • 956
  • 1
  • 18
  • 32
Shadow2531
  • 11,980
  • 5
  • 35
  • 48
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

d0ugal
  • 459
  • 5
  • 11
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;
andersh
  • 8,105
  • 6
  • 39
  • 30
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 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 "";
}
Eduardo
  • 39
  • 1
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);
  • That's more-or-less the same as the "Update: no need to use regex" code in the [highest-voted answer](http://stackoverflow.com/a/647272/) above. There's also loads of similar code in [this question](http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript)). You're missing `decodeURIComponent` on the extracted strings at least. – Rup Feb 17 '14 at 11:00
  • @Rup, the update was made after this answer. – Qwerty Jun 12 '14 at 08: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 Jun 12 '14 at 09:40
  • @Rup Yup, sorry. And yup. – Qwerty Jun 12 '14 at 09:46
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.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
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

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'
André Snede
  • 9,899
  • 7
  • 43
  • 67
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
Pranavan Maru
  • 481
  • 5
  • 10
  • Neat, but apart from the way you remove the leading `?` that's basically the same as the two answers above you? – Rup Aug 04 '14 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. – Pranavan Maru Aug 08 '14 at 07:49
1

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

Ben
  • 2,962
  • 2
  • 20
  • 26
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]);
        }
    }
}
Shadow2531
  • 11,980
  • 5
  • 35
  • 48
  • You can also .toLowerCase() the name if you want hfname matching to be case-insensitive. – Shadow2531 Mar 15 '09 at 05: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 Mar 15 '09 at 05: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 Mar 15 '09 at 05:41
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

Eric Anderson
  • 3,692
  • 4
  • 31
  • 34
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. :)

core
  • 32,451
  • 45
  • 138
  • 193
  • 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 Mar 15 '09 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 Mar 15 '09 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 Nov 01 '11 at 08:06