一个Javascript对象的查询string编码
你知道一个快速和简单的方法来编码一个Javascript对象的string
,我可以通过GET
请求?
没有jQuery
,没有其他的框架 – 只是纯Javascript的:)
喜欢这个?
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
编辑:这一个也转换recursion对象(使用PHP“数组”表示查询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
jQuery有一个函数jQuery.param()
,如果你已经在使用它,你可以使用: http : //api.jquery.com/jquery.param/
例:
var params = { width:1680, height:1050 }; var str = jQuery.param( params );
str
现在包含width=1680&height=1050
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
编辑:我喜欢这一行,但我敢打赌,这将是一个更受欢迎的答案,如果它符合接受答案的语义:
function serialize( obj ) { return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&') }
这里是ES6中的一个class轮:
Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
使用Node.js v6.6.3
const querystring = require('querystring') const obj = { foo: 'bar', baz: 'tor' } let result = querystring.stringify(obj) // foo=bar&baz=tor
参考: https : //nodejs.org/api/querystring.html
user187291对已接受解决scheme的一个小修改:
serialize = function(obj) { var str = []; for(var p in obj){ if (obj.hasOwnProperty(p)) { str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); } } return str.join("&"); }
在对象上检查hasOwnProperty可以使JSLint / JSHint高兴,并且如果对象不是简单的字典,它可以防止意外地序列化对象或其他东西的方法。 请参阅本页上的段落: http : //javascript.crockford.com/code.html
你需要发送任意对象吗? 如果是这样,GET是一个坏主意,因为用户代理和Web服务器将接受的URL的长度是有限制的。 我的build议是build立一个名称 – 值对的数组发送,然后build立一个查询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() );
使用JSON。
看看这个问题的想法如何实施。
这是接受的答案的咖啡文本版本。 这可能会节省时间给某人。
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("&")
Rails / PHP风格查询生成器
这个方法将一个Javascript对象转换成一个URI Query String
。 还处理嵌套的数组和对象(在Rails
/ PHP
语法中):
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('&'); }
用法示例:
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
如果你想recursion地转换一个嵌套对象,并且该对象可能包含或不包含数组(而数组可能包含对象或数组等),那么解决scheme会变得更复杂一点。 这是我的尝试。
我还添加了一些选项,以select是否要为每个对象成员logging它所在的主对象的深度,并select是否将标签添加到来自转换数组的成员。
理想情况下,你应该testing一下thing参数是否真的接收到一个对象或数组。
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; }
好吧,这是一个较旧的post,但我面临这个问题,我已经find了我的个人解决scheme..也许可以帮助别人..
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; };
除了可接受的解决scheme外,它还可以处理对象和对象数组:
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("&"); }
如果你正在使用asp.net mvc动作方法中的对象参数,也添加了objName。
稍微好看一点
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("&"); }
这个跳过空值/未定义的值
export function urlEncodeQueryParams(data) { const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : ''); return params.filter(value => !!value).join('&'); }
我build议使用URLSearchParams接口:
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())
如果你有很多的嵌套对象,上面的答案填充不工作。 相反,你可以从这里select函数参数 – https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js它对我来说非常好!;
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, '+'); };
这里有一个简单的和recursion的Object.entries版本。 它处理任意嵌套的数组,但不嵌套对象。 它也删除空的元素:
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('&'); }
例如:
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"
只是另一种方式(没有recursion对象):
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 }) );
从answer @ user187291引用,添加“isArray”作为参数,使json嵌套数组进行转换。
data : { staffId : "00000001", Detail : [ { "identityId" : "123456" }, { "identityId" : "654321" } ], }
做出结果:
= STAFFID 00000001&明细[0] = .identityId 123456&明细[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);