Reputation: 16074
Is there a fast and simple way to encode a JavaScript object into a string
that I can pass via a GET request?
No jQuery, no other frameworks—just plain JavaScript :)
Upvotes: 738
Views: 669516
Reputation: 467
Here is a one-liner:
const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
Upvotes: 23
Reputation: 79
In ES7, you can write this in one line:
const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
Upvotes: 4
Reputation: 147
I have a simpler solution that does not use any third-party library and is already apt to be used in any browser that has "Object.keys" (aka all modern browsers + Edge + Internet Explorer):
In ES5:
function(a){
if( typeof(a) !== 'object' )
return '';
return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`;
}
In ES3:
function(a){
if( typeof(a) !== 'object' )
return '';
return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}
Upvotes: 5
Reputation: 6008
Referring to the answer user187291, add "isArray" as a parameter to make the JSON nested array be converted.
data : {
staffId : "00000001",
Detail : [ {
"identityId" : "123456"
}, {
"identityId" : "654321"
} ],
}
To make the result,
staffId=00000001&Detail[0].identityId=123456&Detail[1].identityId=654321
use:
serialize = function(obj, prefix, isArray) {
var str = [], p = 0;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
var k, v;
if (isArray)
k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
else
k = prefix ? prefix + "." + p + "" : p, v = obj[p];
if (v !== null && typeof v === "object") {
if (Array.isArray(v)) {
serialize(v, k, true);
} else {
serialize(v, k, false);
}
} else {
var query = k + "=" + v;
str.push(query);
}
}
}
return str.join("&");
};
serialize(data, "prefix", false);
Upvotes: 0
Reputation: 1189
A small amendment to the accepted solution by user187291:
serialize = function(obj) {
var str = [];
for(var p in obj){
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
}
return str.join("&");
}
Checking for hasOwnProperty on the object makes JSLint and JSHint happy, and it prevents accidentally serializing methods of the object or other stuff if the object is anything but a simple dictionary. See the paragraph on for statements on Code Conventions for the JavaScript Programming Language.
Upvotes: 26
Reputation: 1
For TS
const convertQueryToString = (data: { [x: string]: any }): string => {
const serialize = (obj: { [x: string]: any }, prefix?: string): string => {
const str = [];
let p;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
const k = prefix ? `${prefix}[${p}]` : p;
const v = obj[p];
str.push(
v !== null && typeof v === 'object' ? serialize(v, k) : `${encodeURIComponent(k)}=${encodeURIComponent(v)}`
);
}
}
return str.join('&');
};
return serialize(data);
};
Upvotes: -1
Reputation: 324567
If you need to send arbitrary objects, then GET is a bad idea since there are limits to the lengths of URLs that user agents and web servers will accepts. My suggestion would be to build up an array of name-value pairs to send and then build up a query string:
function QueryStringBuilder() {
var nameValues = [];
this.add = function(name, value) {
nameValues.push( {name: name, value: value} );
};
this.toQueryString = function() {
var segments = [], nameValue;
for (var i = 0, len = nameValues.length; i < len; i++) {
nameValue = nameValues[i];
segments[i] = encodeURIComponent(nameValue.name) + "=" + encodeURIComponent(nameValue.value);
}
return segments.join("&");
};
}
var qsb = new QueryStringBuilder();
qsb.add("veg", "cabbage");
qsb.add("vegCount", "5");
alert( qsb.toQueryString() );
Upvotes: 12
Reputation: 3726
jQuery has a function for this, jQuery.param(). If you're already using it, you can use this:
Example:
var params = { width:1680, height:1050 };
var str = jQuery.param( params );
str
now contains width=1680&height=1050
.
Upvotes: 253
Reputation: 18530
Here's the CoffeeScript version of the accepted answer.
serialize = (obj, prefix) ->
str = []
for p, v of obj
k = if prefix then prefix + "[" + p + "]" else p
if typeof v == "object"
str.push(serialize(v, k))
else
str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v))
str.join("&")
Upvotes: 7
Reputation: 3631
Use:
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
I like this one-liner, but I bet it would be a more popular answer if it matched the accepted answer semantically:
function serialize( obj ) {
let str = '?' + Object.keys(obj).reduce(function(a, k){
a.push(k + '=' + encodeURIComponent(obj[k]));
return a;
}, []).join('&');
return str;
}
Upvotes: 139
Reputation: 41
This is an addition for the accepted solution. This works with objects and array of objects:
parseJsonAsQueryString = function (obj, prefix, objName) {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
var v = obj[p];
if (typeof v == "object") {
var k = (objName ? objName + '.' : '') + (prefix ? prefix + "[" + p + "]" : p);
str.push(parseJsonAsQueryString(v, k));
} else {
var k = (objName ? objName + '.' : '') + (prefix ? prefix + '.' + p : p);
str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
//str.push(k + "=" + v);
}
}
}
return str.join("&");
}
Also I have added objName if you're using object parameters, like in ASP.NET MVC action methods.
Upvotes: 4
Reputation: 981
const querystring = require('querystring')
const obj = {
foo: 'bar',
baz: 'tor'
}
let result = querystring.stringify(obj)
// foo=bar&baz=tor
Reference: Query string
Upvotes: 70
Reputation: 21
The previous answers do not work if you have a lot of nested objects.
Instead you can pick the function parameter from jquery-param/jquery-param.js. It worked very well for me!
var param = function (a) {
var s = [], rbracket = /\[\]$/,
isArray = function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}, add = function (k, v) {
v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v;
s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
}, buildParams = function (prefix, obj) {
var i, len, key;
if (prefix) {
if (isArray(obj)) {
for (i = 0, len = obj.length; i < len; i++) {
if (rbracket.test(prefix)) {
add(prefix, obj[i]);
} else {
buildParams(prefix + '[' + (typeof obj[i] === 'object' ? i : '') + ']', obj[i]);
}
}
} else if (obj && String(obj) === '[object Object]') {
for (key in obj) {
buildParams(prefix + '[' + key + ']', obj[key]);
}
} else {
add(prefix, obj);
}
} else if (isArray(obj)) {
for (i = 0, len = obj.length; i < len; i++) {
add(obj[i].name, obj[i].value);
}
} else {
for (key in obj) {
buildParams(key, obj[key]);
}
}
return s;
};
return buildParams('', a).join('&').replace(/%20/g, '+');
};
Upvotes: 2
Reputation: 75750
This method converts a JavaScript object into a URI query string. It also handles nested arrays and objects (in Ruby on Rails and PHP syntax):
function serializeQuery(params, prefix) {
const query = Object.keys(params).map((key) => {
const value = params[key];
if (params.constructor === Array)
key = `${prefix}[]`;
else if (params.constructor === Object)
key = (prefix ? `${prefix}[${key}]` : key);
if (typeof value === 'object')
return serializeQuery(value, key);
else
return `${key}=${encodeURIComponent(value)}`;
});
return [].concat.apply([], query).join('&');
}
Example Usage:
let params = {
a: 100,
b: 'has spaces',
c: [1, 2, 3],
d: { x: 9, y: 8}
}
serializeQuery(params)
// returns 'a=100&b=has%20spaces&c[]=1&c[]=2&c[]=3&d[x]=9&d[y]=8
Upvotes: 32
Reputation: 49
A single line to convert an object into a query string in case somebody needs it again:
let Objs = { a: 'obejct-a', b: 'object-b' }
Object.keys(objs).map(key => key + '=' + objs[key]).join('&')
// The result will be a=object-a&b=object-b
Upvotes: 4
Reputation: 2171
const params = {
a: 1,
b: 'query stringify',
c: null,
d: undefined,
f: '',
g: { foo: 1, bar: 2 },
h: ['Winterfell', 'Westeros', 'Braavos'],
i: { first: { second: { third: 3 }}}
}
static toQueryString(params = {}, prefix) {
const query = Object.keys(params).map((k) => {
let key = k;
const value = params[key];
if (!value && (value === null || value === undefined || isNaN(value))) {
value = '';
}
switch (params.constructor) {
case Array:
key = `${prefix}[]`;
break;
case Object:
key = (prefix ? `${prefix}[${key}]` : key);
break;
}
if (typeof value === 'object') {
return this.toQueryString(value, key); // for nested objects
}
return `${key}=${encodeURIComponent(value)}`;
});
return query.join('&');
}
toQueryString(params)
"a=1&b=query%20stringify&c=&d=&f=&g[foo]=1&g[bar]=2&h[]=Winterfell&h[]=Westeros&h[]=Braavos&i[first][second][third]=3"
Upvotes: 4
Reputation: 1040
Here is a simple implementation that gets an object and converts it to a query parameters string:
export function objectToQueryParams(queryParams: object): string {
return queryParams ?
Object.entries(queryParams).reduce((acc, [key, val], index) => {
const sign = index === 0 ? '?' : '&';
acc += `${sign}${encodeURIComponent(key)}=${encodeURIComponent(val)}`;
return acc;
}, '')
: '';
}
Upvotes: 0
Reputation: 17410
My implementation of encoding an object as a query string, using reduce
:
export const encodeAsQueryString = (params) => (
Object.keys(params).reduce((acc, key)=>(
params.hasOwnProperty(key) ? (
[...acc, encodeURIComponent(key) + '=' + encodeURIComponent(params[key])]
) : acc
), []).join('&')
);
Upvotes: 0
Reputation: 3710
I've written a package just for that: object-query-string :)
It supports nested objects, arrays, custom encoding functions, etc. It is lightweight and jQuery-free.
// TypeScript
import { queryString } from 'object-query-string';
// Node.js
const { queryString } = require("object-query-string");
const query = queryString({
filter: {
brands: ["Audi"],
models: ["A4", "A6", "A8"],
accidentFree: true
},
sort: 'mileage'
});
returns
filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage
Upvotes: 2
Reputation: 7851
If you want to pass an entire object as a single parameter, e.g, ?filter={param1: "val1", param2: "val2"}
:
const serializeObject = (obj) => {
let objStr = JSON.stringify(obj);
objStr = objStr.replace(/\{/g, encodeURIComponent("{"));
objStr = objStr.replace(/}/g, encodeURIComponent("}"));
objStr = objStr.replace(/:/g, encodeURIComponent(":"));
return objStr;
};
let res = serializeObject({param1: "val1", param2: "val2"});
console.log("serializeObject:", res); //%7B"param1"%3A"val1","param2"%3A"val2"%7D
console.log("serializeObject-decoded:", decodeURIComponent(res)); //{"param1":"val1","param2":"val2"}
Upvotes: 0
Reputation: 4282
While there are limits to query-string lengths that should be considered (for sending JSON data in HTTP/s GET calls versus using POST)...
JSON.stringify(yourJSON) will create a String from your JSON object.
Then just hex-encode it (link below).
That will work always versus various possible problems with base64 type URL encoding, UTF-8 characters, nested JSON objects and such.
Upvotes: -1
Reputation: 889
There another popular library, qs. You can add it by:
yarn add qs
And then use it like this:
import qs from 'qs'
const array = { a: { b: 'c' } }
const stringified = qs.stringify(array, { encode: false })
console.log(stringified) //-- outputs a[b]=c
Upvotes: 6
Reputation: 3455
It can handle recursive objects or arrays in the standard query form, like a=val&b[0]=val&b[1]=val&c=val&d[some key]=val
. Here's the final function.
const objectToQueryString = (initialObj) => {
const reducer = (obj, parentPrefix = null) => (prev, key) => {
const val = obj[key];
key = encodeURIComponent(key);
const prefix = parentPrefix ? `${parentPrefix}[${key}]` : key;
if (val == null || typeof val === 'function') {
prev.push(`${prefix}=`);
return prev;
}
if (['number', 'boolean', 'string'].includes(typeof val)) {
prev.push(`${prefix}=${encodeURIComponent(val)}`);
return prev;
}
prev.push(Object.keys(val).reduce(reducer(val, prefix), []).join('&'));
return prev;
};
return Object.keys(initialObj).reduce(reducer(initialObj), []).join('&');
};
const testCase1 = {
name: 'Full Name',
age: 30
}
const testCase2 = {
name: 'Full Name',
age: 30,
children: [
{name: 'Child foo'},
{name: 'Foo again'}
],
wife: {
name: 'Very Difficult to say here'
}
}
console.log(objectToQueryString(testCase1));
console.log(objectToQueryString(testCase2));
Expand the snippet below to verify the result in your browser -
const objectToQueryString = (initialObj) => {
const reducer = (obj, parentPrefix = null) => (prev, key) => {
const val = obj[key];
key = encodeURIComponent(key);
const prefix = parentPrefix ? `${parentPrefix}[${key}]` : key;
if (val == null || typeof val === 'function') {
prev.push(`${prefix}=`);
return prev;
}
if (['number', 'boolean', 'string'].includes(typeof val)) {
prev.push(`${prefix}=${encodeURIComponent(val)}`);
return prev;
}
prev.push(Object.keys(val).reduce(reducer(val, prefix), []).join('&'));
return prev;
};
return Object.keys(initialObj).reduce(reducer(initialObj), []).join('&');
};
const testCase1 = {
name: 'Full Name',
age: 30
}
const testCase2 = {
name: 'Full Name',
age: 30,
children: [
{name: 'Child foo'},
{name: 'Foo again'}
],
wife: {
name: 'Very Difficult to say here'
}
}
console.log(objectToQueryString(testCase1));
console.log(objectToQueryString(testCase2));
functions
, null
, and undefined
keys
and values
for empty objects and arrays.new Number(1)
or new String('my string')
because no one should ever do thatUpvotes: 3
Reputation: 145
Use:
const objectToQueryParams = (o = {}) =>
Object.entries(o)
.map((p) => `${encodeURIComponent(p[0])}=${encodeURIComponent(p[1])}`)
.join("&");
Refer to the below gist for more: https://gist.github.com/bhaireshm
Upvotes: 1
Reputation: 3461
/**
* Converts an object into a Cookie-like string.
* @param toSerialize object or array to be serialized
* @param prefix used in deep objects to describe the final query parameter
* @returns ampersand separated key=value pairs
*
* Example:
* ```js
* serialize({hello:[{world: "nice"}]}); // outputs "hello[0][world]=nice"
* ```
* ---
* Adapted to TS from a StackOverflow answer https://stackoverflow.com/a/1714899/4537906
*/
const serialize = (toSerialize: unknown = {}, prefix?: string) => {
const keyValuePairs = [];
Object.keys(toSerialize).forEach((attribute) => {
if (Object.prototype.hasOwnProperty.call(toSerialize, attribute)) {
const key = prefix ? `${prefix}[${attribute}]` : attribute;
const value = toSerialize[attribute];
const toBePushed =
value !== null && typeof value === "object"
? serialize(value, key)
: `${key}=${value}`;
keyValuePairs.push(toBePushed);
}
});
return keyValuePairs.join("&");
};
Upvotes: 1
Reputation: 280
Use:
const toQueryString = obj => "?".concat(Object.keys(obj).map(e => `${encodeURIComponent(e)}=${encodeURIComponent(obj[e])}`).join("&"));
const data = {
offset: 5,
limit: 10
};
toQueryString(data); // => ?offset=5&limit=10
const data = {
offset: 5,
limit: 10
};
new URLSearchParams(data).toString(); // => ?offset=5&limit=10
Both the above methods will set the value as null if not present. If you want not to set the query parameter if value is null then use:
const toQueryString = obj => "?".concat(Object.keys(obj).map(e => obj[e] ? `${encodeURIComponent(e)}=${encodeURIComponent(obj[e])}` : null).filter(e => !!e).join("&"));
const data = {
offset: null,
limit: 10
};
toQueryString(data); // => "?limit=10" else with above methods "?offset=null&limit=10"
You can freely use any method.
Upvotes: 7
Reputation: 41
URLSearchParams looks good, but it didn't work for nested objects.
Try to use
encodeURIComponent(JSON.stringify(object))
Upvotes: 1
Reputation: 1
You can pass an object to this function with undefined properties. If the property exist, it will be converted to a query string and the query string will be returned.
function convertToQueryString(props) {
const objQueryString = { ...props };
for (const key in objQueryString) {
if (!key) {
delete objQueryString[key];
}
}
const params = JSON.stringify(objQueryString);
const qs = params
.replace(/[/''""{}]/g, '')
.replace(/[:]/g, '=')
.replace(/[,]/g, '&');
console.log(qs)
return qs;
}
convertToQueryString({order: undefined, limit: 5, page: 1})
Upvotes: -1
Reputation: 53940
Like this:
serialize = function(obj) {
var str = [];
for (var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
console.log(serialize({
foo: "hi there",
bar: "100%"
}));
// foo=hi%20there&bar=100%25
This one also converts recursive objects (using PHP "array" notation for the query string):
serialize = function(obj, prefix) {
var str = [],
p;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p,
v = obj[p];
str.push((v !== null && typeof v === "object") ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
return str.join("&");
}
console.log(serialize({
foo: "hi there",
bar: {
blah: 123,
quux: [1, 2, 3]
}
}));
// foo=hi%20there&bar%5Bblah%5D=123&bar%5Bquux%5D%5B0%5D=1&bar%5Bquux%5D%5B1%5D=2&bar%5Bquux%5D%5B2%5D=3
Upvotes: 982
Reputation: 9
let data = {
id:1,
name:'Newuser'
};
const getqueryParam = data => {
let datasize = Object.keys(data).length;
let initial = '?';
Object.keys(data).map(function (key, index) {
initial = initial.concat(`${key}=${data[key]}`);
index != datasize - 1 && (initial = initial.concat('&'));
});
console.log(initial, 'MyqueryString');
return initial;
};
console.log(getqueryParam(data))//You can get the query string here
If you have baseUrl means to get full query use
baseUrl.concat(getqueryParam(data))
Upvotes: -1