171

Is there any way to create the query parameters for doing a GET request in JavaScript?

Just like in Python you have urllib.urlencode(), which takes in a dictionary (or list of two tuples) and creates a string like 'var1=value1&var2=value2'.

Csa77
  • 559
  • 10
  • 19
cnu
  • 34,209
  • 22
  • 63
  • 63
  • Reverse question: [url - How can I get query string values in JavaScript? - Stack Overflow](https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript) – user202729 Nov 04 '21 at 05:19

14 Answers14

219

Here you go:

function encodeQueryData(data) {
   const ret = [];
   for (let d in data)
     ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
   return ret.join('&');
}

Usage:

const data = { 'first name': 'George', 'last name': 'Jetson', 'age': 110 };
const querystring = encodeQueryData(data);
Gibolt
  • 33,561
  • 12
  • 157
  • 107
Shog9
  • 152,046
  • 34
  • 225
  • 232
  • 16
    When iterating with `for`, use [hasOwnProperty](http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/hasOwnProperty) to ensure interoperability. – troelskn Sep 21 '08 at 19:29
  • 3
    @troelskn, good point... although in this case, someone would have to be extending Object.prototype to break it, which is a pretty bad idea to start with. – Shog9 Sep 21 '08 at 19:57
  • 1
    @Shog9 Why is it a bad ideia? – Cesar Canassa Sep 14 '11 at 23:55
  • @Cesar, see: http://stackoverflow.com/questions/3832617/what-are-the-benefits-and-dangers-of-adding-methods-to-object-prototype-in-javasc** – Shog9 Sep 15 '11 at 00:01
  • Downvote because I have no idea whether this solution acts according to the specification and will always work. Prefer the standard URLSearchParams that is now available. OP please consider retreating this outdated answer. – masterxilo Mar 06 '20 at 08:45
  • this is insufficient. `encodeQueryData({foo:{bar:123}})` returns `foo=%5Bobject%20Object%5D` , but the correct return value would be `foo%5Bbar%5D=123` – hanshenrik Dec 11 '20 at 12:54
  • This is the new correct way. `function encodeQueryData(data) { return new URLSearchParams(data).toString(); }` – LP Square Mar 02 '22 at 11:09
175

URLSearchParams has increasing browser support.

const data = {
  var1: 'value1',
  var2: 'value2'
};

const searchParams = new URLSearchParams(data);

// searchParams.toString() === 'var1=value1&var2=value2'

Node.js offers the querystring module.

const querystring = require('querystring');

const data = {
  var1: 'value1',
  var2: 'value2'
};

const searchParams = querystring.stringify(data);

// searchParams === 'var1=value1&var2=value2'
Andrew Palmer
  • 1,993
  • 2
  • 14
  • 14
  • 1
    Definitely the clean and modern approach. You can also later freely call `searchParams.append(otherData)` – kano Dec 16 '19 at 19:28
  • 4
    URLSearchParams will parse White space as '+' instead of '%20'. For example, `new URLSearchParams({ abc: 'a b c' }).toString()`result in `'abc=a+b+c'` – wrkwrk Oct 14 '20 at 06:22
  • How is it that in 2021 there is not a more standardized way of achieving this? For example, what about adding `?` only when `searchParams` are not blank. – francistheturd Sep 29 '21 at 20:00
83

functional

function encodeData(data) {
    return Object.keys(data).map(function(key) {
        return [key, data[key]].map(encodeURIComponent).join("=");
    }).join("&");
}   
Manav
  • 9,646
  • 6
  • 41
  • 50
  • 1
    Nice one! .map() has been implemented in JavaScript 1.6 so almost all browsers, even the granny ones support it. But as you can guess IE does not except IE 9+. But do not worry, there is a workaround. Source: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map#Browser_compatibility – Akseli Palén Feb 13 '13 at 11:24
  • `var data = { bloop1: true, bloop2: "something" }; var url = "https://something.com/?"; var params = encodeData(data); var finalUrl = url + params; // Is this the right use?` Should produce `https://www.something.com/?bloop1=true&bloop2=something` ? – dylanh724 Oct 20 '17 at 04:13
  • 1
    @DylanHunt: Yup… – Przemek May 20 '18 at 19:27
  • this is insufficient. `encodeData({foo:{bar:123}})` returns `foo=%5Bobject%20Object%5D` , but the correct return value would be `foo%5Bbar%5D=123` – hanshenrik Dec 11 '20 at 12:56
40

Zabba has provided in a comment on the currently accepted answer a suggestion that to me is the best solution: use jQuery.param().

If I use jQuery.param() on the data in the original question, then the code is simply:

const params = jQuery.param({
    var1: 'value',
    var2: 'value'
});

The variable params will be

"var1=value&var2=value"

For more complicated examples, inputs and outputs, see the jQuery.param() documentation.

Kirby
  • 14,280
  • 7
  • 86
  • 100
14

ES2017 (ES8)

Making use of Object.entries(), which returns an array of object's [key, value] pairs. For example, for {a: 1, b: 2} it would return [['a', 1], ['b', 2]]. It is not supported (and won't be) only by IE.

Code:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

Example:

buildURLQuery({name: 'John', gender: 'male'});

Result:

"name=John&gender=male"
Przemek
  • 3,631
  • 1
  • 23
  • 33
10

We've just released arg.js, a project aimed at solving this problem once and for all. It's traditionally been so difficult but now you can do:

var querystring = Arg.url({name: "Mat", state: "CO"});

And reading works:

var name = Arg("name");

or getting the whole lot:

var params = Arg.all();

and if you care about the difference between ?query=true and #hash=true then you can use the Arg.query() and Arg.hash() methods.

csga5000
  • 3,836
  • 4
  • 38
  • 52
Mat Ryer
  • 3,437
  • 3
  • 25
  • 24
9

This should do the job:

const createQueryParams = params => 
      Object.keys(params)
            .map(k => `${k}=${encodeURI(params[k])}`)
            .join('&');

Example:

const params = { name : 'John', postcode: 'W1 2DL'}
const queryParams = createQueryParams(params)

Result:

name=John&postcode=W1%202DL
eaorak
  • 5,284
  • 1
  • 24
  • 18
  • 1
    I've later realized that it's actually a slightly different version of @manav's response below. But anyway, it could still be preferable for ES6 syntax. – eaorak Mar 16 '18 at 17:26
  • 1
    First of all, you are not encoding the keys. Also, you should use `encodeURIComponent()` instead of `encodeURI`. [Read about the difference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#Description). – Przemek May 20 '18 at 15:25
8

If you are using Prototype there is Form.serialize

If you are using jQuery there is Ajax/serialize

I do not know of any independent functions to accomplish this, though, but a google search for it turned up some promising options if you aren't currently using a library. If you're not, though, you really should because they are heaven.

Paolo Bergantino
  • 466,948
  • 77
  • 516
  • 433
  • 6
    jQuery.param() takes object and transform it to GET query string (this function better matches the question). – Tim Jul 21 '15 at 18:20
5

Just like to revisit this almost 10 year old question. In this era of off-the-shelf programming, your best bet is to set your project up using a dependency manager (npm). There is an entire cottage industry of libraries out there that encode query strings and take care of all the edge cases. This is one of the more popular ones -

https://www.npmjs.com/package/query-string

pscl
  • 3,128
  • 23
  • 28
3

A little modification to typescript:

  public encodeData(data: any): string {
    return Object.keys(data).map((key) => {
      return [key, data[key]].map(encodeURIComponent).join("=");
    }).join("&");
  }
Clayton K. N. Passos
  • 1,132
  • 11
  • 15
0

I have improved the function of shog9`s to handle array values

function encodeQueryData(data) {
    const ret = [];
    for (let d in data) {
        if (typeof data[d] === 'object' || typeof data[d] === 'array') {
            for (let arrD in data[d]) {
                ret.push(`${encodeURIComponent(d)}[]=${encodeURIComponent(data[d][arrD])}`)
            }
        } else if (typeof data[d] === 'null' || typeof data[d] === 'undefined') {
            ret.push(encodeURIComponent(d))
        } else {
            ret.push(`${encodeURIComponent(d)}=${encodeURIComponent(data[d])}`)
        }

    }
    return ret.join('&');
}

Example

let data = {
  user: 'Mark'
  fruits: ['apple', 'banana']
}

encodeQueryData(data) // user=Mark&fruits[]=apple&fruits[]=banana
  • this is an improvement, yes, but it's still insufficient: `encodeQueryData({foo:{bar:123}})` returns `foo[]=123` , but the correct return value would be `foo%5Bbar%5D=123` – hanshenrik Dec 11 '20 at 13:01
0

By using queryencoder, you can have some nice-to-have options, such custom date formatters, nested objects and decide if a val: true will be just value or value=true.

const { encode } = require('queryencoder');

const object = {
    date: new Date('1999-04-23')
};

// The result is 'date=1999-04-23'
const queryUrl = encode(object, {
    dateParser: date => date.toISOString().slice(0, 10)
});
EuberDeveloper
  • 583
  • 8
  • 24
0

Here is an example:

let my_url = new URL("https://stackoverflow.com")
my_url.pathname = "/questions"

const parameters = {
    title: "just",
    body: 'test'
}

Object.entries(parameters).forEach(([name, value]) => my_url.searchParams.set(name, value))

console.log(my_url.href)

-12

This thread points to some code for escaping URLs in php. There's escape() and unescape() which will do most of the work, but the you need add a couple extra things.

function urlencode(str) {
str = escape(str);
str = str.replace('+', '%2B');
str = str.replace('%20', '+');
str = str.replace('*', '%2A');
str = str.replace('/', '%2F');
str = str.replace('@', '%40');
return str;
}

function urldecode(str) {
str = str.replace('+', ' ');
str = unescape(str);
return str;
}
Csa77
  • 559
  • 10
  • 19
Kibbee
  • 64,201
  • 27
  • 140
  • 180