Do you know 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 :)

asked Nov 11 '09 at 12:07
Napolux

6,73553154
 
    
Why can't JQuery be a solution if there is an appropriate one for your solution? – eaglei22 Mar 30 '17 at 22:38
    
@eaglei22 because at the time I was working on a project for an IPTV set top box device and no external libraries were allowed. ;-) – Napolux Mar 31 '17 at 8:22
1  
Thanks for the response. I see this specification from time to time and always wondered a scenario why. Well, now I got one, thanks! :) – eaglei22 Mar 31 '17 at 13:48
4  
@eaglei22 Because sometimes you don't want to load a large library to get one element by id. – Aaron HarunJun 26 '17 at 20:46
 
up vote576down voteaccepted

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

Edit: 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
 
2  
Thanks a lot, that's the fast&clean solution I was looking for! – Napolux Nov 11 '09 at 12:43
8  
note p should be encodeURIComponent-ed too – bobince Nov 11 '09 at 12:43
2  
Won't it break given {foo: [1,2,3], bar: "100%" } ? – Quentin Nov 11 '09 at 12:53
1  
@Ofri: For POST requests to a server set up to receive it, JSON is a good choice. For GET requests, if you're sending anything other than a few simple parameters to the server then it's likely your design is wrong. – Tim Down Nov 11 '09 at 14:25
2  
@Marcel That's because the function doesn't check for hasOwnProperty. I've updated your fiddle so now it does: jsfiddle.net/rudiedirkx/U5Tyb/1 – Rudie Jan 5 '13 at 18:22

jQuery has a function for this, jQuery.param(), if you're already using it you can use that:http://api.jquery.com/jquery.param/

example:

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

str now contains width=1680&height=1050

answered Dec 15 '11 at 12:43
benvds

2,77611114
 
78  
quoting Napolux (the OP): "just plain Javascript". :P – Sk8erPeter Jul 18 '12 at 15:53
67  
+1 This is still useful because I'm already using jQuery. – David Harkness Jul 31 '12 at 20:44
5  
jQuery.param() has sinister behavior. Try to execute var a = []; a[2564] = 12; console.log(jQuery.param({ propertylist: a })); to see what I mean. – akond Aug 14 '13 at 12:32
10  
@akond The jQuery documentation specifically says that you may not pass in a bare array. – Ariel Jun 26 '14 at 20:47
1  
@Ariel that line is only valid if the argument to param is an array. Passing in an object that contains an array does not invoke any of those rules. – Chris Hall Dec 11 '14 at 17:52 
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

Edit: 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 ) {
return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
}
answered Aug 8 '13 at 1:02
sergk

2,6151313
 
1  
nice. now, that's better. crisp and refreshing. – Todd Jan 7 '15 at 15:47
1  
A dedicated line for the reduct function would greatly improve the readability though. – Aurélien Ribon Apr 20 '15 at 14:48
37  
Using .map() instead of .reduce() would be even simpler: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&') – Jannes Apr 21 '15 at 13:34 
2  
Just to note that Object.keys is only available in IE >= 9 – Johnston Jun 2 '15 at 20:26
1  
Further improved @Jannes code using ES6 templates instead of concatenation - Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&') – csilk Jan 25 '17 at 0:16 

Here's a one liner in ES6:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
answered Feb 15 '16 at 18:14
 
    
replace key w/ k and you're golden – Jamie Kudla Feb 24 '16 at 17:02
    
edited - thanks @Kudla69 – Nico Tejera Feb 25 '16 at 17:46
6  
Warning! This only works on shallow objects. If you have a top-level property that is another object, this one liner will output "key=%5Bobject%20Object%5D". Just as a heads up. – Andrew Allbright Apr 5 '16 at 18:47
1  
Also, this doesn't spit up arrays. I got export?actions[]=finance,create,edit when it should have export?actions[]=finance&actions[]=create&actions[]=edit as is the awful standard. – darkbluesun Aug 11 '16 at 3:15 
    
Arrays are pretty much always "you're on your own" because URL arguments are just strings as far as the spec is concerned, so you're on the hook to make anything that isn't a single string gets read correctly by the server you're calling. actions[] is PHP notation; Django uses multiple action instead (no [] suffix); some other ORM/CMS require comma-separated lists, etc. So "if it's not simple strings, first make sure you know what your server even wants". – Mike 'Pomax' Kamermans Jan 23 '17 at 19:01 

With Node.js v6.6.3

const querystring = require('querystring')

const obj = {
foo: 'bar',
baz: 'tor'
} let result = querystring.stringify(obj)
// foo=bar&baz=tor

Reference: https://nodejs.org/api/querystring.html

answered Jul 7 '16 at 2:07
 
4  
This shouldn't be downvoted IMO, if it's JS on the server this should be the correct answer. – Michael BeninAug 11 '16 at 18:11
1  
It seems like it doesn't support nested objects. – Yarin Gold Jan 1 '17 at 13:30
1  
Quote from original question: "No jQuery, no other frameworks - just plain Javascript :)" – Brian Hannay May 10 '17 at 17:05 

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/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 in this page: http://javascript.crockford.com/code.html

answered Feb 26 '13 at 18:50
jssebastian

619712
 

Do you need to send arbitrary objects? If so, 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() );
answered Nov 11 '09 at 12:32
Tim Down

226k50349440
 

use JSON.

take a look at this question for ideas on how to implement.

answered Nov 11 '09 at 12:34
Ofri Raviv

16.4k23745
 
2  
I don't know what he's writing the server in, but most modern languages have good packages that read JSON. Besides, even if he ends up implementing it, its better to implement a JSON-reading server code than to invent a new encoding scheme of your own. DIY encodings like this tend to be buggy (because you usually don't think of all the possible cases, like the value being an array in itself etc'). – Ofri Raviv Nov 11 '09 at 13:43
    
are you basically suggesting to convert teh object into JSON and then pass the entire JSON string to the server as a single GET query parameter? – Marco Demaio Nov 13 '12 at 18:24
    
Yes. It seems what OP is asking for. – Ofri Raviv Nov 13 '12 at 19:38
    
not too elegant, but functional; +1 from me. – vaxquis Oct 21 '17 at 16:34

Here's the coffeescript version of accepted answer. This might save time to someone.

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("&")
answered Aug 13 '12 at 17:43
alf

14.2k104678
 
    
Thanks alfonso! Really saved my time! – Lukas Nov 27 '13 at 15:35

Rails / PHP Style Query Builder

This method converts a Javascript object into a URI Query String. Also handles nested arrays and objects (in Rails / 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
answered Mar 5 '17 at 5:18
Sheharyar

33.1k689131
 
    
Nice example. I fixed a typo in your answer. By the way, would be interesting if you edit your function to exclude falsy values (null, undefined, NaN, '')... – developer033 Apr 29 '17 at 22:44

I suggest using the URLSearchParams interface:

const searchParams = new URLSearchParams();
const search = {foo: "hi there", bar: "100%" };
Object.keys(search).forEach(key => searchParams.append(key, search[key]));
console.log(searchParams.toString())
answered Jun 17 '17 at 20:48
bmaggi

408610
 
    
This should be the accepted answer – rorymorris89 Dec 19 '17 at 13:32

If you want to convert a nested object recursively and the object may or may not contain arrays (and the arrays may contain objects or arrays, etc), then the solution gets a little more complex. This is my attempt.

I've also added some options to choose if you want to record for each object member at what depth in the main object it sits, and to choose if you want to add a label to the members that come from converted arrays.

Ideally you should test if the thing parameter really receives an object or array.

function thingToString(thing,maxDepth,recordLevel,markArrays){
//thing: object or array to be recursively serialized
//maxDepth (int or false):
// (int) how deep to go with converting objects/arrays within objs/arrays
// (false) no limit to recursive objects/arrays within objects/arrays
//recordLevel (boolean):
// true - insert "(level 1)" before transcript of members at level one (etc)
// false - just
//markArrays (boolean):
// insert text to indicate any members that came from arrays
var result = "";
if (maxDepth !== false && typeof maxDepth != 'number') {maxDepth = 3;}
var runningDepth = 0;//Keeps track how deep we're into recursion //First prepare the function, so that it can call itself recursively
function serializeAnything(thing){
//Set path-finder values
runningDepth += 1;
if(recordLevel){result += "(level " + runningDepth + ")";} //First convert any arrays to object so they can be processed
if (thing instanceof Array){
var realObj = {};var key;
if (markArrays) {realObj['type'] = "converted array";}
for (var i = 0;i < thing.length;i++){
if (markArrays) {key = "a" + i;} else {key = i;}
realObj[key] = thing[i];
}
thing = realObj;
console.log('converted one array to ' + typeof realObj);
console.log(thing);
} //Then deal with it
for (var member in thing){
if (typeof thing[member] == 'object' && runningDepth < maxDepth){
serializeAnything(thing[member]);
//When a sub-object/array is serialized, it will add one to
//running depth. But when we continue to this object/array's
//next sibling, the level must go back up by one
runningDepth -= 1;
} else if (maxDepth !== false && runningDepth >= maxDepth) {
console.log('Reached bottom');
} else
if (
typeof thing[member] == "string" ||
typeof thing[member] == 'boolean' ||
typeof thing[member] == 'number'
){
result += "(" + member + ": " + thing[member] + ") ";
} else {
result += "(" + member + ": [" + typeof thing[member] + " not supported]) ";
}
}
}
//Actually kick off the serialization
serializeAnything(thing); return result; }
answered Jul 13 '12 at 8:45
Wytze

5,68543958
 
    
Thanks for the recursive approach – Sherlock Aug 11 '15 at 4:49

Here's a concise & recursive version with Object.entries. It handles arbitrarily nested arrays, but not nested objects. It also removes empty elements:

const format = (k,v) => v !== null ? `${k}=${encodeURIComponent(v)}` : ''

const to_qs = (obj) => {
return [].concat(...Object.entries(obj)
.map(([k,v]) => Array.isArray(v)
? v.map(arr => to_qs({[k]:arr}))
: format(k,v)))
.filter(x => x)
.join('&');
}

E.g.:

let json = {
a: [1, 2, 3],
b: [], // omit b
c: 1,
d: "test&encoding", // uriencode
e: [[4,5],[6,7]], // flatten this
f: null, // omit nulls
g: 0
}; let qs = to_qs(json) => "a=1&a=2&a=3&c=1&d=test%26encoding&e=4&e=5&e=6&e=7&g=0"
answered Mar 29 '17 at 22:29
mikebridge

1,68511729
 

ok, it's a older post but i'm facing this problem and i have found my personal solution.. maybe can help someone else..

     function objToQueryString(obj){
var k = Object.keys(obj);
var s = "";
for(var i=0;i<k.length;i++) {
s += k[i] + "=" + encodeURIComponent(obj[k[i]]);
if (i != k.length -1) s += "&";
}
return s;
};
answered Aug 6 '13 at 20:17
hayatoShingu

415511
 

Addition for accepted solution, this works with objects & 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 have added objName if you're using object parameters like in asp.net mvc action methods.

answered Jun 2 '16 at 1:55
 

A little bit look better

objectToQueryString(obj, prefix) {
return Object.keys(obj).map(objKey => {
if (obj.hasOwnProperty(objKey)) {
const key = prefix ? `${prefix}[${objKey}]` : objKey;
const value = obj[objKey]; return typeof value === "object" ?
this.objectToQueryString(value, key) :
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
} return null;
}).join("&");
}
answered Sep 14 '16 at 20:42
Pavel

146113
 

This one skips null/undefined values

export function urlEncodeQueryParams(data) {
const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : '');
return params.filter(value => !!value).join('&');
}
answered Feb 13 '17 at 3:34
nimatra

343316
 

The above answers fill not work if you have a lot of nested objects. Instead you can pick the function param from here - https://github.com/knowledgecode/jquery-param/blob/master/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, '+');
};
answered Jan 19 '17 at 13:22
 

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 + ie):

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('&');
}
answered Dec 26 '17 at 10:47
 

Just another way (no recursive object):

   getQueryString = function(obj)
{
result = ""; for(param in obj)
result += ( encodeURIComponent(param) + '=' + encodeURIComponent(obj[param]) + '&' ); if(result) //it's not empty string when at least one key/value pair was added. In such case we need to remove the last '&' char
result = result.substr(0, result.length - 1); //If length is zero or negative, substr returns an empty string [ref. http://msdn.microsoft.com/en-us/library/0esxc5wy(v=VS.85).aspx] return result;
} alert( getQueryString({foo: "hi there", bar: 123, quux: 2 }) );
answered Nov 13 '12 at 18:51
Marco Demaio

17.8k29100137
 
    
Why the negative vote? – Marco Demaio Sep 22 '14 at 18:07

Refer from the answer @user187291, add "isArray" as parameter to make the json nested array to be converted.

data : {
staffId : "00000001",
Detail : [ {
"identityId" : "123456"
}, {
"identityId" : "654321"
} ], }

To make the result :

staffId=00000001&Detail[0].identityId=123456&Detail[1].identityId=654321

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);

 

https://stackoverflow.com/questions/1714786/query-string-encoding-of-a-javascript-object

把Javascript 对象转换为键值对连接符字符串的方法总结的更多相关文章

  1. Javascript对象数据类型(键值对)的创建和使用方法

    对象数据类型(键值对) 1.创建键值对 var arry={name:"小明",age:20,isgey:falet} // var 键值对名 = {键:值,键:值} 2.增加键值 ...

  2. JavaScript中对象转换为原始值的规则

    JavaScript中对象转换为原始值遵循哪些原则? P52 对象到布尔值对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为true.对于包装对象亦是如此:new Boolean(fal ...

  3. 关于JavaScript对象的键和值

    一个JavaScript对象由键和值组成. 当一个给定键的值被设置为一个字符串.布尔值.数字.数组或对象时,我们把这个键称为属性. 当把键设置为函数时,我们把它叫做方法.

  4. json转换为键值对辅助类

    /// <summary> /// json转换为键值对辅助类 /// </summary> public class JsonParser { private static ...

  5. 使用Javascript/jQuery将javascript对象转换为json格式数据 - 海涛的CSDN博客 - 博客频道 - CSDN.NET

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  6. JavaScript —— 对象的取值与赋值

    可能是因为用惯了 Java ,对一个对象取值/赋值喜欢用 setXXX() 和 getXXX() . 在 JavaScript 中使用 setValue() 时,遇到了个奇怪的问题,所以查了下 Jav ...

  7. C# 给枚举定义DescriptionAttribute,把枚举转换为键值对

    在C#中,枚举用来定状态值很方便,例如我定义一个叫做Season的枚举 public enum Season { Spring = 1, Summer = 2, Autumn = 3, Winter ...

  8. .net c#将数据库数据对象转换为实体值对象

    using System; using System.Data; namespace Sunlib { public static class DataHelper { //将数据库数据对象转换为实体 ...

  9. js对象替换键值名称

    js对象替换键值名称 将obj中的id和name字段替换分别替换成为“@id”,“@name” 代码如下: let obj = [{id:,name:,name:"李四"}].ma ...

随机推荐

  1. LOJ3120. 「CTS2019」珍珠 [容斥,生成函数]

    传送门 思路 非常显然,就是要统计有多少种方式使得奇数的个数不超过\(n-2m\).(考场上这个都没想到真是身败名裂了--) 考虑直接减去钦点\(n-2m+1\)个奇数之后的方案数,但显然这样会算重, ...

  2. php安装扩展的地址

    1 查看扩展 phpinfo  or extention_loads  or php -m 下载扩展地址 http://pecl.php.net     or http://windows.php.n ...

  3. sed基础

    sed  文本流编辑的  行编辑器 hold space :保持空间.仓库,半成品 一次从文件中读取一行,放到自己编辑的内存缓冲空间即模式空间,不会编辑原文件:根据所给定的命令在模式空间中做编辑处理, ...

  4. pip 安装指定版本的工具

    记录一下避免忘记 安装facebook-business的版本在3.0 到 4.0之间的最新版本, == : 指定版本号 pip install "facebook-business> ...

  5. Golang的文件处理方式-常见的读写

    在 Golang 语言中,文件使用指向 os.File 类型的指针来表示的,也叫做文件句柄.注意,标准输入 os.Stdin 和标准输出 os.Stdout ,他们的类型都是 *os.File 哟.在 ...

  6. 【零基础】风格迁移之deep-painterly-harmonization的安装和使用

    注:原项目名叫deep-painterly-harmonization,这里我缩写下称呼其为“DPH” 注:原项目GIT链接:https://github.com/luanfujun/deep-pai ...

  7. 学号20175313 《实现Linux下Sort -t : -k 2功能》第十二周

    目录 一.题目要求 二.题目理解 三.设计思路 四.代码实现 五.代码链接 六.运行结果截图 七.参考资料 一.题目要求 实现Linux下Sort -t : -k 2的功能 二.题目理解 -t 分隔符 ...

  8. 如何查看appPackage和启动appActivity

    安装apk,模拟器或真机中在前台运行该应用程序,获取appPackage,即应用包名 appPackage:  adb shell dumpsys activity | find "mFoc ...

  9. 如何构建自己的docker镜像

    需求情况:springboot项目想要部署到docker里面,如何部署? 步骤如下: 1.将jar包上传linux服务器 /usr/local/dockerapp 目录,在jar包所在目录创建名为 D ...

  10. Flutter移动电商实战 --(31)列表页_列表切换交互制作

    点击左侧的大类右边的小类也跟着变化 新建provide 要改变哪里就建哪里的provide,我们现在要改变的是右边的商品列表的数组. category_goods_list.dart 这样我们的pro ...