283

Just wondering if there is anything built-in to Javascript that can take a Form and return the query parameters, eg: "var1=value&var2=value2&arr[]=foo&arr[]=bar..."

I've been wondering this for years.

Liam
30k28 gold badges145 silver badges206 bronze badges
asked Nov 25, 2008 at 9:13
3

23 Answers 23

430

The URLSearchParams API is available in all modern browsers. For example:

const params = new URLSearchParams({
 var1: "value",
 var2: "value2",
 arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"

pomber
24.1k15 gold badges83 silver badges96 bronze badges
answered Apr 6, 2018 at 22:37
Sign up to request clarification or add additional context in comments.

9 Comments

Best answer here imo. Just to add to it, you can do params.append(key, value) later for adding new search params in more complicated scenarios.
Note that undefined and null values are included on the final string: x=null&y=undefined
Also, if you already have an URL object (for example const url = new URL("https://stackoverflow.com")), you can set its query strings url.search = new URLSearchParams({foo: "bar"}) or url.searchParams.append("foo", "bar")
Note that TS will warn about using a plain object, but it works fine nonetheless
Note, it encodes entities differently than encodeURIComponent(): spaces here are encoded as + rather than %20. Not sure if that may be the reason of issues with some services.
|
261

2k20 update: use Josh's solution with URLSearchParams.toString().

Old answer:


Without jQuery

var params = {
 parameter1: 'value_1',
 parameter2: 'value 2',
 parameter3: 'value&3' 
};
var esc = encodeURIComponent;
var query = Object.keys(params)
 .map(k => esc(k) + '=' + esc(params[k]))
 .join('&');

For browsers that don't support arrow function syntax which requires ES5, change the .map... line to

 .map(function(k) {return esc(k) + '=' + esc(params[k]);})
answered Dec 10, 2015 at 18:44

5 Comments

Best solution I've seen yet - very clean and concise. A couple of caveats, though. 1) in the .map(), both k and params[k] should be encoded, e.g. encodeURIComponent(k) and encodeURIComponent(params[k]). 2) You are allowed to have more than one instance of a named parameter in a query string. If you want that capability, you'll have to use an array instead of an object (most applications won't want or need that).
3) Not all browsers will support arrow function syntax (that requires ES5). If you want to support all browsers (and encode the parts), replace the above .map() with .map(function(k) {return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]);})
The & in the third value value&3 is not intentional, right? Or is it just there to demonstrate the encoding is working?
@user1738579 I edited the answer to also include your example for non-ES5.
If you're going the ES6 route, you can also use template strings to get rid of the concat: .map( k => `${esc(k)}=${esc(params[k])}` )
149

If you're using jQuery you might want to check out jQuery.param() http://api.jquery.com/jQuery.param/

Example:

var params = {
 parameter1: 'value1',
 parameter2: 'value2',
 parameter3: 'value3' 
};
var query = $.param(params);
console.log(query);

This will print out:

parameter1=value1&parameter2=value2&parameter3=value3
KARASZI István
31.6k9 gold badges107 silver badges133 bronze badges
answered Aug 31, 2012 at 13:40

7 Comments

This is actually the correct answer! The query string for a form is $.param($('#myform').serializeArray()).
@Jesse, that would be the same result as: $('#myform').serialize()
jQuery !== JavaScript
@gphilip Well that's why I started the response with "If you're using jQuery ...". Otherwise if you want to implement it in vanilla JS you can examine the implementation of jQuery.param() here github.com/jquery/jquery/blob/master/src/serialize.js :)
Unlike my answer this one supports nested objects like someStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
|
59

This doesn't directly answer your question, but here's a generic function which will create a URL that contains query string parameters. The parameters (names and values) are safely escaped for inclusion in a URL.

function buildUrl(url, parameters){
 var qs = "";
 for(var key in parameters) {
 var value = parameters[key];
 qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
 }
 if (qs.length > 0){
 qs = qs.substring(0, qs.length-1); //chop off last "&"
 url = url + "?" + qs;
 }
 return url;
}
// example:
var url = "http://example.com/";
var parameters = {
 name: "George Washington",
 dob: "17320222"
};
console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222
Umut Sirin
2,5021 gold badge23 silver badges31 bronze badges
answered Mar 17, 2011 at 14:45

6 Comments

Is there any built-in function similar to this one in one of the populars javascript frameworks like jquery, mootools, etc...?
A more robust native JavaScript solution is at stackoverflow.com/a/1714899/1269037
Weirdest implementation ever, why do you need to initialize a new Array while you actually use it as an object? o,O
@UmutSirin Lol yeah I didn't know a lot about Javascript at the time. xD I think I was treating it like a PHP array. Feel free to refactor if you want.
@Michael Haha, yeah. I just sent an edit. Thank you for the answer!
|
39

Create an URL object and append the values to seachParameters

let stringUrl = "http://www.google.com/search";
let url = new URL(stringUrl);
let params = url.searchParams;
params.append("q", "This is seach query");
console.log(url.toString());

The output will be

http://www.google.com/search?q=This+is+seach+query
Audwin Oyong
2,5273 gold badges21 silver badges37 bronze badges
answered Oct 4, 2020 at 0:40

Comments

22

With jQuery you can do this by $.param

$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"
answered Oct 10, 2012 at 10:02

Comments

22

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"
answered May 20, 2018 at 20:04

1 Comment

14

querystring can help.

So, you can

const querystring = require('querystring')
url += '?' + querystring.stringify(parameters)
answered Mar 2, 2017 at 22:43

2 Comments

For frontend applications you might also consider npmjs.com/package/qs
@RobertPankowecki, yes, qs is better and already in my arsenal, cheers!
10

No, I don't think standard JavaScript has that built in, but Prototype JS has that function (surely most other JS frameworks have too, but I don't know them), they call it serialize.

I can reccomend Prototype JS, it works quite okay. The only drawback I've really noticed it it's size (a few hundred kb) and scope (lots of code for ajax, dom, etc.). Thus if you only want a form serializer it's overkill, and strictly speaking if you only want it's Ajax functionality (wich is mainly what I used it for) it's overkill. Unless you're careful you may find that it does a little too much "magic" (like extending every dom element it touches with Prototype JS functions just to find elements) making it slow on extreme cases.

answered Nov 25, 2008 at 9:30

2 Comments

Just wondering if there's anything built-in. Seems like there should be. I hate prototype, but I'm not holding that against you :)
When JavaScript was designed, Ajax was not yet discovered, therfore parsing a form just to get the querystring (that it would creati itself when submitted) probably did not make much sense. Today it does, tough... Btw, compared to script.aculo.us, prototype is nice. :)
7

If you don't want to use a library, this should cover most/all of the same form element types.

function serialize(form) {
 if (!form || !form.elements) return;
 var serial = [], i, j, first;
 var add = function (name, value) {
 serial.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
 }
 var elems = form.elements;
 for (i = 0; i < elems.length; i += 1, first = false) {
 if (elems[i].name.length > 0) { /* don't include unnamed elements */
 switch (elems[i].type) {
 case 'select-one': first = true;
 case 'select-multiple':
 for (j = 0; j < elems[i].options.length; j += 1)
 if (elems[i].options[j].selected) {
 add(elems[i].name, elems[i].options[j].value);
 if (first) break; /* stop searching for select-one */
 }
 break;
 case 'checkbox':
 case 'radio': if (!elems[i].checked) break; /* else continue */
 default: add(elems[i].name, elems[i].value); break;
 }
 }
 }
 return serial.join('&');
}
answered Nov 25, 2008 at 11:04

1 Comment

Thanks! I was just facing the same problem as the original poster, and your function was exactly what I needed.
5

You can do that nowadays with FormData and URLSearchParams without the need to loop over anything.

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();

Older browsers will need a polyfill, though.

answered Oct 9, 2018 at 13:51

Comments

5

Might be a bit redundant but the cleanest way i found which builds on some of the answers here:

const params: {
 key1: 'value1',
 key2: 'value2',
 key3: 'value3',
}
const esc = encodeURIComponent;
const query = Object.keys(params)
 .map(k => esc(k) + '=' + esc(params[k]))
 .join('&');
return fetch('my-url', {
 method: 'POST',
 headers: {'Content-Type': 'application/x-www-form-urlencoded'},
 body: query,
})

Source

answered Apr 2, 2020 at 12:52

Comments

5

The UrlSearchParams API is a great suggestion, but I can't believe nobody mentioned the incredibly useful .get and .set methods. They can be used to manipulate the query string and not only they're very easy to use, they also solve a number of issues you might encounter. For example, in my case I wanted to build a query string without duplicate keys. .set solves this problem for you. Quoting from the MDN docs:

URLSearchParams.set() Sets the value associated with a given search parameter to the given value. If there are several values, the others are deleted.

Example (from MDN):

let url = new URL('https://example.com?foo=1&bar=2');
let params = new URLSearchParams(url.search);
// Add a third parameter
params.set('baz', 3);
params.toString(); // "foo=1&bar=2&baz=3"

Alternative, shorter syntax:

let url = new URL('https://example.com?foo=1&bar=2');
// Add a third parameter
url.searchParams.set('baz', 3);
url.searchParams.toString(); // "foo=1&bar=2&baz=3"
answered Oct 6, 2021 at 20:03

3 Comments

The last line should probably be url.searchParams.toString();
Actually, it's still wrong. You changed params.toString(); to url.toString();. In my opinion it should be url.searchParams.toString(); (since the OP wants only the query string, not the whole URL).
Oh, sorry, I guess I should have re-read the question! Fixed now.
3

I'm not entirely certain myself, I recall seeing jQuery did it to an extent, but it doesn't handle hierarchical records at all, let alone in a php friendly way.

One thing I do know for certain, is when building URLs and sticking the product into the dom, don't just use string-glue to do it, or you'll be opening yourself to a handy page breaker.

For instance, certain advertising software in-lines the version string from whatever runs your flash. This is fine when its adobes generic simple string, but however, that's very naive, and blows up in an embarrasing mess for people whom have installed Gnash, as gnash'es version string happens to contain a full blown GPL copyright licences, complete with URLs and <a href> tags. Using this in your string-glue advertiser generator, results in the page blowing open and having imbalanced HTML turning up in the dom.

The moral of the story:

 var foo = document.createElement("elementnamehere"); 
 foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
 somenode.appendChild(foo); 

Not:

 document.write("<elementnamehere attribute=\"" 
 + ilovebrokenwebsites 
 + "\">" 
 + stringdata 
 + "</elementnamehere>");

Google need to learn this trick. I tried to report the problem, they appear not to care.

answered Nov 25, 2008 at 9:28

1 Comment

Right on. Document.write is so 1995, anyway.
3

I know this is very late answer but works very well...

var obj = {
a:"a",
b:"b"
}
Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");

note: object.entries will return key,values pairs

output from above line will be a=a&b=b

Hope its helps someone.

Happy Coding...

answered Feb 18, 2020 at 11:12

1 Comment

it doesn't encode at all
2

As Stein says, you can use the prototype javascript library from http://www.prototypejs.org. Include the JS and it is very simple then, $('formName').serialize() will return what you want!

answered Nov 25, 2008 at 9:52

Comments

2

For those of us who prefer jQuery, you would use the form plugin: http://plugins.jquery.com/project/form, which contains a formSerialize method.

answered Nov 25, 2008 at 14:03

Comments

2

Using URL and URLSearchParams

let url = new URL("https://foo.bar");
url.search = new URLSearchParams({
 customerid: 12345,
 lang: "en"
}).toString();
console.log(url.toString());
answered Mar 7, 2024 at 8:14

Comments

1

You don't actually need a form to do this with Prototype. Just use Object.toQueryString function:

Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
Rimian
38.7k17 gold badges129 silver badges119 bronze badges
answered Jan 5, 2009 at 14:48

2 Comments

Granted, you answered nearly 10 years ago, but this code is now deprecated.
Such a function would be badass! Why did they deprecate it?
1

Is is probably too late to answer your question.
I had the same question and I didn't like to keep appending strings to create a URL. So, I started using $.param as techhouse explained.
I also found a URI.js library that creates the URLs easily for you. There are several examples that will help you: URI.js Documentation.
Here is one of them:

var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"
uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"
uri.setSearch("goodbye", "sun");
// uri == "?hello=mars&foo=bar&goodbye=sun"
// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter...
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`
answered Aug 12, 2015 at 23:24

Comments

1

Remove undefined params 💪😃

 urlParams = obj =>{
 const removeUndefined = JSON.parse(JSON.stringify(obj))
 const result = new URLSearchParams(removeUndefined).toString();
 return result ? `?${result}`: '';
 }
 console.log(urlParams({qwe: undefined, txt: 'asd'})) // '?txt=asd'
 console.log(urlParams({qwe: undefined})) // ''

answered Sep 29, 2022 at 4:31

Comments

0

These answers are very helpful, but i want to add another answer, that may help you build full URL. This can help you concat base url, path, hash and parameters.

var url = buildUrl('http://mywebsite.com', {
 path: 'about',
 hash: 'contact',
 queryParams: {
 'var1': 'value',
 'var2': 'value2',
 'arr[]' : 'foo'
 }
 });
 console.log(url);

You can download via npm https://www.npmjs.com/package/build-url

Demo:

;(function () {
 'use strict';
 var root = this;
 var previousBuildUrl = root.buildUrl;
 var buildUrl = function (url, options) {
 var queryString = [];
 var key;
 var builtUrl;
 var caseChange; 
 
 // 'lowerCase' parameter default = false, 
 if (options && options.lowerCase) {
 caseChange = !!options.lowerCase;
 } else {
 caseChange = false;
 }
 if (url === null) {
 builtUrl = '';
 } else if (typeof(url) === 'object') {
 builtUrl = '';
 options = url;
 } else {
 builtUrl = url;
 }
 if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
 builtUrl = builtUrl.slice(0, -1);
 } 
 if (options) {
 if (options.path) {
 var localVar = String(options.path).trim(); 
 if (caseChange) {
 localVar = localVar.toLowerCase();
 }
 if (localVar.indexOf('/') === 0) {
 builtUrl += localVar;
 } else {
 builtUrl += '/' + localVar;
 }
 }
 if (options.queryParams) {
 for (key in options.queryParams) {
 if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
 var encodedParam;
 if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
 for(var i = 0; i < options.queryParams[key].length; i++) {
 encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
 queryString.push(key + '=' + encodedParam);
 }
 } else { 
 if (caseChange) {
 encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
 }
 else {
 encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
 }
 queryString.push(key + '=' + encodedParam);
 }
 }
 }
 builtUrl += '?' + queryString.join('&');
 }
 if (options.hash) {
 if(caseChange)
 builtUrl += '#' + String(options.hash).trim().toLowerCase();
 else
 builtUrl += '#' + String(options.hash).trim();
 }
 } 
 return builtUrl;
 };
 buildUrl.noConflict = function () {
 root.buildUrl = previousBuildUrl;
 return buildUrl;
 };
 if (typeof(exports) !== 'undefined') {
 if (typeof(module) !== 'undefined' && module.exports) {
 exports = module.exports = buildUrl;
 }
 exports.buildUrl = buildUrl;
 } else {
 root.buildUrl = buildUrl;
 }
}).call(this);
var url = buildUrl('http://mywebsite.com', {
		path: 'about',
		hash: 'contact',
		queryParams: {
			'var1': 'value',
			'var2': 'value2',
			'arr[]' : 'foo'
		}
	});
	console.log(url);

answered Apr 15, 2019 at 8:11

Comments

0

var params = { width:1680, height:1050 };
var str = jQuery.param( params );
console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

answered Jul 10, 2019 at 6:21

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.