Skip to content

Instantly share code, notes, and snippets.

@pirate
Last active December 15, 2023 07:17
Show Gist options
  • Save pirate/9298155edda679510723 to your computer and use it in GitHub Desktop.
Save pirate/9298155edda679510723 to your computer and use it in GitHub Desktop.
Parse URL query parameters in ES6
function getUrlParams(search) {
const hashes = search.slice(search.indexOf('?') + 1).split('&')
const params = {}
hashes.map(hash => {
const [key, val] = hash.split('=')
params[key] = decodeURIComponent(val)
})
return params
}
console.log(getUrlParams(window.location.search))
@tbillington
Copy link

tbillington commented Aug 13, 2018

Note: the above functions all trim any characters including & following the first equal sign in a query value.

Eg ?q=test=abc will be returned as test by the above functions.

Obligatory own version of the above ;)

const decodeURLParams = search => {
  const hashes = search.slice(search.indexOf("?") + 1).split("&");
  return hashes.reduce((params, hash) => {
    const split = hash.indexOf("=");
    const key = hash.slice(0, split);
    const val = hash.slice(split + 1);
    return Object.assign(params, { [key]: decodeURIComponent(val) });
  }, {});
};

@budnieswski
Copy link

Improving the @tbillington answer, when only have the key, the key loses the last letter and the value, instead of empty, is assigned with the key.

Eg ?debug&name=John&last-name
will be returned: {debu: "debug", name: "John", last-nam: "last-name"}
instead of: {debug: null, name: "John", last-name: null}

The code:

const decodeURLParams = search => {
    const hashes = search.slice(search.indexOf("?") + 1).split("&");
    return hashes.reduce((params, hash) => {
        const split = hash.indexOf("=");

        if (split < 0) {
            return Object.assign(params, {
                [hash]: null
            });
        }

        const key = hash.slice(0, split);
        const val = hash.slice(split + 1);

        return Object.assign(params, { [key]: decodeURIComponent(val) });
    }, {});
};

@cancerberoSgx
Copy link

What about hash ? http://foo.com/#?a=1 What about hash ? http://foo.com/#/?a=1 What about hash ? http://foo.com/?b=2#?a=1

@gtzilla
Copy link

gtzilla commented Nov 15, 2019

@cancerbergoSgx
How about cheating and treating as a search string?

// URL hash http://foo.com/?c=2#?a=1&b=works
new URLSearchParams(document.location.hash.replace('#','?')).get('b')
// returns 'works'  
// Chrome Version 78.0.3904.87 (Official Build) (64-bit)

You would still need to parse document.location.search and merge the two objects if you wanted a unified search plus hash parameters data structure.

What about hash ? http://foo.com/#?a=1 What about hash ? http://foo.com/#/?a=1 What about hash ? http://foo.com/?b=2#?a=1

@arondiploma
Copy link

How to handle the value with equal(=) sign? like:

keyA=value1&keyB=hff92hfgg=&keyC=value3

@pirate
Copy link
Author

pirate commented Jan 9, 2020

That's not a valid value @zerocoolElite, it needs to be URL-encoded (= becomes %3D when URL-encoded).

@arondiploma
Copy link

That's not a valid value @zerocoolElite, it needs to be URL-encoded (= becomes %3D when URL-encoded).

Then the search string should be encoded first before passing to getUrlParams()?

@legend80s
Copy link

legend80s commented Mar 8, 2020

I've tested all the functions above by https://runkit.com/embed/n18yhf9u2nqc and the conclusion is that url-parse and URLSearchParams is the rightest and most expected ones against the standard url - Node.js built-in module. Even the query-string module is not work as expected.

const search = '?abc=foo&def=[asf]&xyz==5&flag&&double&q=test1=test2&keyB=hff92hfgg=';

console.log((search));

const url = require('url')
console.log('0. url - the Node.js built-in module √');
console.log(url.parse(search, true).query);

console.log('1. queryString ×');
console.log(queryString.parse(search));

const parse = require('url-parse')
console.log('2. url-parse √');
console.log(parse(search, true).query);

console.log('3. URLSearchParams √');
console.log([...new URLSearchParams(search).entries()].reduce((q, [k, v]) => Object.assign(q, {[k]: v}), {}))

result:

?abc=foo&def=[asf]&xyz==5&flag&&double&q=test1=test2&keyB=hff92hfgg=

0. url - the Node.js built-in module √
Object {abc: "foo", def: "[asf]", double: "", flag: "", keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}

1. queryString ×
Object {: null, abc: "foo", def: "[asf]", double: null, flag: null, keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}

2. url-parse √
Object {abc: "foo", def: "[asf]", double: "", flag: "", keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}

3. URLSearchParams √
Object {abc: "foo", def: "[asf]", double: "", flag: "", keyB: "hff92hfgg=", q: "test1=test2", xyz: "=5"}

@raveren
Copy link

raveren commented Apr 21, 2020

So this fails if you have select multiple - or any other input with multiple values that's named with square brackets:

<select name="statuses[]" multiple>...

Here's a slight adjustment, hopefully I'm not stepping on any edge cases:

function getUrlParams(search) {
    const hashes = search.slice(search.indexOf('?') + 1).split('&')
    const params = {}
    hashes.map(hash => {
        let [key, val] = hash.split('=')
        key = decodeURIComponent(key)
        if (key.indexOf('[') > -1) { // handle multiple type inputs
            if (typeof params[key] === 'undefined') {
                params[key] = []
            }

            params[key].push(decodeURIComponent(val))
        } else {
            params[key] = decodeURIComponent(val)
        }
    })
    return params
}

@eyecatchup
Copy link

eyecatchup commented Apr 24, 2020

Unfortunately even the native URLSearchParams implementation doesn't handle array query parameters. :(

So, here's another take on array query parameters. Tested on

https://gist.github.com/pirate/9298155edda679510723?abc=foo&def=[asf]&xyz==5&flag&&double&q=test1=test2&keyB=hff92hfgg=&arr[]=ArrayValue1&arr[]=ArrayValue2&arr[]=ArrayValue3&arr2[0]=ArrayValue1&arr2[1]=ArrayValue2&arr2[2]=ArrayValue3&fields=kind,items(title,characteristics/length)
const getQueryParams = () => {
    let params = {};
    (new URLSearchParams(document.location.search)).forEach((d, e) => {
      let a = decodeURIComponent(e), c = decodeURIComponent(d)
      if (a.endsWith("[]")) {
        a = a.replace("[]", ""), params[a] || (params[a] = []), params[a].push(c)
      } else {
        let b = a.match(/\[([a-z0-9_\/\s,.-])+\]$/g)
        b ? (a = a.replace(b, ""), b = b[0].replace("[", "").replace("]", ""), params[a] || (params[a] = []), params[a][b] = c) : params[a] = c
      }
    })
    return params
}

@marcodpt
Copy link

marcodpt commented May 9, 2021

I create an alternative project if you want to use es6 module, with a very simple api:
query

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment