JavaScript对象的查询字符串编码

是否有一个快速和简单的方法来编码JavaScript对象到string,我可以通过得到请求传递?

没有jQuery,没有其他框架——只有纯JavaScript:)

572318 次浏览

是这样的:

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

它还转换递归对象(使用PHP "数组"查询字符串的符号):

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

如果您需要发送任意对象,那么GET是一个坏主意,因为有限制的url长度,用户代理和web服务器将接受。我的建议是建立一个名称-值对数组来发送,然后建立一个查询字符串:

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

jQuery有一个函数,jQuery.param ()。如果你已经在使用它,你可以使用这个:

例子:

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

str现在包含width=1680&height=1050

如果您想递归地转换嵌套对象,并且对象可能包含也可能不包含数组(数组可能包含对象或数组等),那么解决方案就会变得稍微复杂一些。这就是我的尝试。

我还添加了一些选项,用于选择是否要为每个对象成员记录它位于主对象中的深度,以及选择是否要向来自已转换数组的成员添加标签。

理想情况下,您应该测试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;


}

以下是公认答案的CoffeeScript版本。

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("&")

另一种方法(没有递归对象):

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

对用户187291接受的解决方案的一个小修改:

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使JSLintJSHint愉快,并且如果对象不是一个简单的字典,它可以防止意外地序列化对象的方法或其他东西。请参阅关于声明 JavaScript编程语言的代码约定的段落。

好吧,这是一个旧的帖子,但我正面临这个问题,我已经找到了我的个人解决方案。也许可以帮助别人…

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

使用:

Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

我喜欢这句话,但我敢打赌,如果它在语义上符合公认的答案,它将是一个更受欢迎的答案:

function serialize( obj ) {
let str = '?' + Object.keys(obj).reduce(function(a, k){
a.push(k + '=' + encodeURIComponent(obj[k]));
return a;
}, []).join('&');
return str;
}

下面是ES6中的一行代码:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');

这是对已接受的解的补充。这适用于对象和对象数组:

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("&");
}

我还添加了objName,如果你使用对象参数,像在ASP。NET MVC动作方法。

使用Node.js v6.6.3

const querystring = require('querystring')


const obj = {
foo: 'bar',
baz: 'tor'
}


let result = querystring.stringify(obj)
// foo=bar&baz=tor

参考:# EYZ0

看起来好一点

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("&");
}

如果有很多嵌套对象,前面的答案就不起作用了。

相反,您可以从jquery-param / 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, '+');
};

这个函数跳过null/undefined值

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

Ruby on Rails和PHP样式的查询生成器

该方法将JavaScript对象转换为URI查询字符串。它还处理嵌套数组和对象(在Ruby on 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

这是一个简明的&使用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"

我建议使用URLSearchParams接口:

const searchParams = new URLSearchParams();
const params = {foo: "hi there", bar: "100%" };
Object.keys(params).forEach(key => searchParams.append(key, params[key]));
console.log(searchParams.toString())

或者像这样将搜索对象传递给构造函数:

const params = {foo: "hi there", bar: "100%" };
const queryString = new URLSearchParams(params).toString();
console.log(queryString);

参考答案@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);

我有一个更简单的解决方案,它不使用任何第三方库,并且已经易于在任何具有“Object”的浏览器中使用。键”(也就是所有现代浏览器+ edge + ie):

< >强ES5

function(a){
if( typeof(a) !== 'object' )
return '';
return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`;
}

< >强在胡状

function(a){
if( typeof(a) !== 'object' )
return '';
return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}

您也可以通过使用简单的JavaScript来实现这一点。

const stringData = '?name=Nikhil&surname=Mahirrao&age=30';
    

const newData= {};
stringData.replace('?', '').split('&').map((value) => {
const temp = value.split('=');
newData[temp[0]] = temp[1];
});


console.log('stringData: '+stringData);
console.log('newData: ');
console.log(newData);

单行转换对象为查询字符串,以防有人再次需要它:

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

在ES7中,你可以用一行写:

const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))

好吧,似乎每个人都把他的俏皮话写在这里,所以我的是:

const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");

const buildSortedQuery = (args) => {
return Object.keys(args)
.sort()
.map(key => {
return window.encodeURIComponent(key)
+ '='
+ window.encodeURIComponent(args[key]);
})
.join('&');
};


console.log(buildSortedQuery({
foo: "hi there",
bar: "100%"
}));


//bar=100%25&foo=hi%20there

我做了一个JSON stringfier的比较,结果如下:

JSON:    {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":"$1,446.35","age":32,"name":"Logan Keller","email":"logankeller@artiq.com","phone":"+1 (952) 533-2258","friends":[{"id":0,"name":"Colon Salazar"},{"id":1,"name":"French Mcneil"},{"id":2,"name":"Carol Martin"}],"favoriteFruit":"banana"}
Rison:   (_id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258')
O-Rison: _id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258'
JSURL:   ~(_id~'5973782bdb9a930533b05cb2~isActive~true~balance~'!1*2c446.35~age~32~name~'Logan*20Keller~email~'logankeller*40artiq.com~phone~'*2b1*20*28952*29*20533-2258~friends~(~(id~0~name~'Colon*20Salazar)~(id~1~name~'French*20Mcneil)~(id~2~name~'Carol*20Martin))~favoriteFruit~'banana)
QS:      _id=5973782bdb9a930533b05cb2&isActive=true&balance=$1,446.35&age=32&name=Logan Keller&email=logankeller@artiq.com&phone=+1 (952) 533-2258&friends[0][id]=0&friends[0][name]=Colon Salazar&friends[1][id]=1&friends[1][name]=French Mcneil&friends[2][id]=2&friends[2][name]=Carol Martin&favoriteFruit=banana
URLON:   $_id=5973782bdb9a930533b05cb2&isActive:true&balance=$1,446.35&age:32&name=Logan%20Keller&email=logankeller@artiq.com&phone=+1%20(952)%20533-2258&friends@$id:0&name=Colon%20Salazar;&$id:1&name=French%20Mcneil;&$id:2&name=Carol%20Martin;;&favoriteFruit=banana
QS-JSON: isActive=true&balance=%241%2C446.35&age=32&name=Logan+Keller&email=logankeller%40artiq.com&phone=%2B1+(952)+533-2258&friends(0).id=0&friends(0).name=Colon+Salazar&friends(1).id=1&friends(1).name=French+Mcneil&friends(2).id=2&friends(2).name=Carol+Martin&favoriteFruit=banana

其中最短的是URL对象表示法

只需使用以下方法:

encodeURIComponent(JSON.stringify(obj))

// elastic search example
let story ={
"query": {
"bool": {
"must": [
{
"term": {
"revision.published": 0,
}
},
{
"term": {
"credits.properties.by.properties.name": "Michael Guild"
}
},
{
"nested": {
"path": "taxonomy.sections",
"query": {
"bool": {
"must": [
{
"term": {
"taxonomy.sections._id": "/science"
}
},
{
"term": {
"taxonomy.sections._website": "staging"
}
}
]
}
}
}
}
]
}
}
}




const whateva = encodeURIComponent(JSON.stringify(story))
console.log(whateva)

ES6解决方案用于JavaScript对象的查询字符串编码

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"

只需使用URLSearchParams这个适用于当前所有浏览器

new URLSearchParams(object).toString()

这是一个开箱即用的。net后端解决方案。我已经采取了这个线程的主要答案,并更新它以适应我们的。net需求。

function objectToQuerystring(params) {
var result = '';


function convertJsonToQueryString(data, progress, name) {
name = name || '';
progress = progress || '';
if (typeof data === 'object') {
Object.keys(data).forEach(function (key) {
var value = data[key];
if (name == '') {
convertJsonToQueryString(value, progress, key);
} else {
if (isNaN(parseInt(key))) {
convertJsonToQueryString(value, progress, name + '.' + key);
} else {
convertJsonToQueryString(value, progress, name + '[' + key+ ']');
}
}
})
} else {
result = result ? result.concat('&') : result.concat('?');
result = result.concat(`${name}=${data}`);
}
}


convertJsonToQueryString(params);
return result;
}
const querystring=  {};


querystring.stringify = function (obj, sep = '&', eq = '=') {
const escape = encodeURIComponent;
const qs = [];
let key = null;


for (key in obj) if (obj.hasOwnProperty(key)) {
qs.push(escape(key) + eq + escape(String(obj[key])));
}
return qs.join(sep);
};

例子:

const a  = querystring.stringify({a: 'all of them', b: true});
console.log(a);  // Output: a=all%20of%20them&b=true
const serialize = obj => Object.keys(obj).reduce((a, b) =>
a.push(encodeURIComponent(b) + "=" + encodeURIComponent(obj[b])) && a,
[]).join("&");

电话:

console.log(serialize({a:1,b:2}));
// output: 'a=1&b=2

这里有一个简单的答案,在转换过程中同时处理字符串和数组。

jsonToQueryString: function (data) {
return Object.keys(data).map((key) => {
if (Array.isArray(data[key])) {
return (`${encodeURIComponent(key)}=${data[key].map((item) => encodeURIComponent(item)).join('%2C')}`);
}
return(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
}).join('&');
}

下面是一个简单的实现,获取一个对象并将其转换为查询参数字符串:

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;
}, '')
: '';
}

我的编码对象作为查询字符串的实现,使用reduce:

export const encodeAsQueryString = (params) => (
Object.keys(params).reduce((acc, key)=>(
params.hasOwnProperty(key) ? (
[...acc, encodeURIComponent(key) + '=' + encodeURIComponent(params[key])]
) : acc
), []).join('&')
);

我为此写了一个包:object-query-string:)

它支持嵌套对象、数组、自定义编码函数等。它是轻量级的,不支持jquery。

// 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'
});


返回

filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage

如果你想将整个对象作为单个参数传递,例如?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"}

Ramda:

    R.pipe(R.toPairs, R.map(R.join('=')), R.join('&'))({a: 'b', b: 'a'})

虽然应该考虑查询字符串长度的限制(在HTTP/s GET调用中发送JSON数据而不是使用POST)…

JSON.stringify(yourJSON)将从JSON对象创建一个String。

然后用十六进制编码(链接如下)。

这将工作总是与各种可能的问题与base64类型的URL编码,UTF-8字符,嵌套JSON对象等。

参考文献

JSON.stringify()

encoding String to HEX

还有另一个流行的库qs。您可以通过以下方式添加:

yarn add qs

然后像这样使用它:

import qs from 'qs'


const array = { a: { b: 'c' } }
const stringified = qs.stringify(array, { encode: false })


console.log(stringified) //-- outputs a[b]=c

以更好的方式做这件事。

它可以处理< >强标准< / >强查询表单中的递归对象或数组,如a=val&b[0]=val&b[1]=val&c=val&d[some key]=val。这是最后一个函数。

逻辑、功能

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

现场测试

展开下面的代码片段,在浏览器中验证结果-

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

需要考虑的事情。

  • 它跳过了functionsnullundefined的值
  • 对于空对象和数组,它跳过keysvalues
  • 它不处理用new Number(1)new String('my string')创建的Number或String对象,因为没有一个人应该这样做

在讨论了一些最重要的答案之后,我编写了另一个实现,它也可以处理一些边缘情况

function serialize(params, prefix) {
return Object.entries(params).reduce((acc, [key, value]) => {
// remove whitespace from both sides of the key before encoding
key = encodeURIComponent(key.trim());


if (params.constructor === Array ) {
key = `${prefix}[]`;
} else if (params.constructor === Object) {
key = (prefix ? `${prefix}[${key}]` : key);
}


/**
*  - undefined and NaN values will be skipped automatically
*  - value will be empty string for functions and null
*  - nested arrays will be flattened
*/
if (value === null || typeof value === 'function') {
acc.push(`${key}=`);
} else if (typeof value === 'object') {
acc = acc.concat(serialize(value, key));
} else if(['number', 'boolean', 'string'].includes(typeof value) && value === value) { // self-check to avoid NaN
acc.push(`${key}=${encodeURIComponent(value)}`);
}


return acc;
}, []);
}


function objectToQueryString(queryParameters) {
return queryParameters ? serialize(queryParameters).join('&'): '';
}


let x = objectToQueryString({
foo: 'hello world',
bar: {
blah: 123,
list: [1, 2, 3],
'nested array': [[4,5],[6,7]] // will be flattened
},
page: 1,
limit: undefined, // field will be ignored
check: false,
max: NaN, // field will be ignored
prop: null,
' key value': 'with spaces' // space in key will be trimmed out
});
  

console.log(x); // foo=hello%20world&bar[blah]=123&bar[list][]=1&bar[list][]=2&bar[list][]=3&bar[nested%20array][][]=4&bar[nested%20array][][]=5&bar[nested%20array][][]=6&bar[nested%20array][][]=7&page=1&check=false&prop=&key%20value=with%20spaces

使用:

const objectToQueryParams = (o = {}) =>
Object.entries(o)
.map((p) => `${encodeURIComponent(p[0])}=${encodeURIComponent(p[1])}`)
.join("&");

参考以下要点: # EYZ0 < / p >

PHP符号的TypeScript版本(没有URL转义版本)

/**
* 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("&");
};

可以将具有未定义属性的对象传递给此函数。如果属性存在,它将被转换为查询字符串并返回查询字符串。

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

URLSearchParams看起来很好,但它不适用于嵌套对象。

试着使用

encodeURIComponent(JSON.stringify(object))
 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

# EYZ0

使用:

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

请注意

以上两个方法都将值设置为null,如果不存在。 如果你不想设置value为空的查询参数,那么使用:

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"

你可以自由使用任何方法。

您可以只加密JSON.stringify()之后的对象,并将其作为一个参数发送。然后在接收到它之后,只需解密它并使用JSON.parse()将其转换为字符串中的对象。