JavaScript http_build_query
Generates a form-encoded query string from an associative array or object.
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 4546 47 48 49 5051 52 | function http_build_query (formdata, numeric_prefix, arg_separator) { // Generates a form-encoded query string from an associative array or object. // // version: 911.815 // discuss at: http://phpjs.org/functions/http_build_query // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Legaev Andrey // + improved by: Michael White (http://getsprink.com) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Brett Zamir (http://brett-zamir.me) // + revised by: stag019 // - depends on: urlencode // * example 1: http_build_query({foo: 'bar', php: 'hypertext processor', baz: 'boom', cow: 'milk'}, '', '&'); // * returns 1: 'foo=bar&php=hypertext+processor&baz=boom&cow=milk' // * example 2: http_build_query({'php': 'hypertext processor', 0: 'foo', 1: 'bar', 2: 'baz', 3: 'boom', 'cow': 'milk'}, 'myvar_'); // * returns 2: 'php=hypertext+processor&myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk' var value, key, tmp = []; var _http_build_query_helper = function (key, val, arg_separator) { var k, tmp = []; if (val === true) { val = "1"; } else if (val === false) { val = "0"; } if (val !== null && typeof(val) === "object") { for (k in val) { if (val[k] !== null) { tmp.push(_http_build_query_helper(key + "[" + k + "]", val[k], arg_separator)); } } return tmp.join(arg_separator); } else if (typeof(val) !== "function") { return this.urlencode(key) + "=" + this.urlencode(val); } else { throw new Error('There was an error processing for http_build_query().'); } }; if (!arg_separator) { arg_separator = "&"; } for (key in formdata) { value = formdata[key]; if (numeric_prefix && !isNaN(key)) { key = String(numeric_prefix) + key; } tmp.push(_http_build_query_helper(key, value, arg_separator)); } return tmp.join(arg_separator); } |
Examples
» Example 1
Running
1 | http_build_query({foo: 'bar', php: 'hypertext processor', baz: 'boom', cow: 'milk'}, '', '&'); |
Should return
1 | 'foo=bar&php=hypertext+processor&baz=boom&cow=milk' |
» Example 2
Running
1 | http_build_query({'php': 'hypertext processor', 0: 'foo', 1: 'bar', 2: 'baz', 3: 'boom', 'cow': 'milk'}, 'myvar_'); |
Should return
1 | 'php=hypertext+processor&myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk' |
Dependencies
In order to use this function, you also need:
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have http_build_query goodness in JavaScript.
D'oh.
Change line 2 from "var key, tmp = []," to "var value, key, tmp = [],".
Add "value = formdata[key];" under line 26.
Change line 30 (or new line 31 if you've added the previous line from "tmp.push(_http_build_query_helper(key, formdata[key], arg_separator));" to "tmp.push(_http_build_query_helper(key, value, arg_separator));".
That should fix'er.
@ stag019: Nice! But I can only replace the current with your implementation if it doesn't break the second example (it does now).
This function fails to handle anything more than one deep, as well as it doesn't handle boolean values the way PHP does.
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 | function http_build_query(formdata, numeric_prefix, arg_separator) { var key, tmp = [], _http_build_query_helper = function (key, val, arg_separator) { var k, tmp = []; if (val === true) { val = "1"; } else if (val === false) { val = "0"; } if (typeof(val) == "array" || typeof(val) == "object") { for(k in val) { if(val[k] !== null) { tmp.push(_http_build_query_helper(key + "[" + k + "]", val[k], arg_separator)); } } return tmp.join(arg_separator); } else if(typeof(val) != "function") { return urlencode(key) + "=" + urlencode(val); } }; if (!arg_separator) { arg_separator = "&"; } for (key in formdata) { if (numeric_prefix && !isNaN(key)) { key = String(numeric_prefix) + key; } tmp.push(_http_build_query_helper(key, formdata[key], arg_separator)); } return tmp.join(arg_separator); } |
@ Michael White: Thanks for bringing it to my attention, yeah your mail is quite big so I saved it for this weekend ;) I'll get back to you today or tomorrow, cheers
No problem. Did you get my email from a couple of days ago? Also, I left a bugfix on the print_r() function that doesn't seem to have been noticed yet.
Well I just found out that escape() is actually not the best thing to use for this function. encodeURIComponent() seems to be required here. The reason behind this is that a literal + sign does not get escaped by escape() and so gets "lost in translation" when working in PHP. I never would have discovered this if I had not been sending values that were either a + or - sign. I have no idea if there are any other characters affected by this at this time. My apologies to anyone who may be affected by this; I thought that escape() worked properly until now.
One more little note:
Replace:
1 | use_val = use_val.replace('%20', '+'); |
with:
1 | use_val = use_val.replace(/%20/g, '+'); |
The original version only replaces a single instance of the string. Using the regular expression with /g at the end tells it to replace "globally" meaning every instance of %20 in the string.
http://crestidg.com
Ooops - forgot the code block....
Replace....
1 2 3 | use_key = encodeURIComponent(key); use_val = encodeURIComponent(formdata[key].toString()); use_val = use_val.replace('%20', '+'); |
1 2 | use_key = escape(key); use_val = escape(formdata[key].toString()); |
Ah - I ran into that problem where the output of encodeURI was incompatible with PHP as well about two months ago.
You have to use escape() instead. PHP likes this one. I've used it for a while in my own Ajax requests.
Legaev Andrey: Thank you, still needed the
1 | use_val = use_val.replace('%20', '+'); |
though, apparently encodeURIComponent does not produce php compatible encoded ouput
Hi!
Key can contain no-ascii character too, and encodeURIComponent() is more appropriate function.
Please, replace code
1 2 3 | use_key = key; use_val = encodeURI(formdata[key].toString()); use_val = use_val.replace('%20', '+'); |
by following:
1 2 | use_key = encodeURIComponent(key); use_val = encodeURIComponent(formdata[key].toString()); |
Key can contain no-ascii character too, and encodeURIComponent() is more appropriate function.


Kevin van Zonneveld
14 Apr '09