将对象文字编码为 Javascript 中的 URL 查询字符串
Encode object literal as URL query string in Javascript
我正在尝试摆脱项目中的 jQuery 依赖项。该项目所做的一件事是像这样将数据发布到服务器:
var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
$.post( url, data);
感谢 You might not need jQuery,我知道如何使用 XMLHttpRequest
:
在纯 Javascript 中重写 $.post
var request = new XMLHttpRequest();
request.open( 'POST', url, true);
request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send( data);
不幸的是,这个描述似乎假定 data
对象已经是一个 URL 编码的查询字符串,而在上面的例子中显然不是这样。事实证明 jQuery 的作用不止于此:对于给定的 data
对象,上面的 $.post
调用将首先将其转换为查询字符串,如下所示:
apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit
使用 XMLHttpRequest
的代码片段不会这样做,因此,服务器会向我抛出错误。
jQuery 也有一个很棒的方法调用 $.param
可以完成这种转换。如果我在最后一行使用
,上面使用 XMLHttpRequest
的代码片段将会非常有效
request.send( $.param(data));
但是,我并没有摆脱 jQuery 依赖。所以我正在寻找 $.param
的纯 Javascript 等价物。有人有类似的东西吗?
注意:问题Plain Javascript Equivalent of jQuery.param()问了一个类似的问题,但接受的答案只适用于非常简单的情况。将该答案中给出的函数应用于我上面的 data
对象会产生:
apple=%5Bobject%20Object%5D%2C%5Bobject%20Object%5D&pear=passion%20fruit
...这与上面给出的$.param(data)
的结果明显不同,并且由于它不能递归工作而丢失了信息。
您可以着手编写递归代码,但为什么不尝试简单的方案 JSON,这就是创建它的原因 - 以更简单的方式在客户端和服务器之间交换数据。
就这样做
request.send(JSON.stringify(data));
JSON.stringify
接受一个对象,然后将其转换为有效的 JSON,可以在服务器端解析。
要了解有关 JSON 的更多信息,没有比浏览它的标签摘录更好的方法了 here
您可以使用编码和解码 URIComponent 函数来完成此操作。
编辑
这个怎么样:
var qs = Object.keys(obj).reduce(function(a,k){
a.push(k+'='+encodeURIComponent(JSON.stringify(obj[k])));
return a;
},[]).join('&');
// "apple=%5B%7B%22kiwi%22%3A%22orange%22%7D%2C%7B%22banana%22%3A%22lemon%22%7D%5D&pear=%22passion%20fruit%22"
而不是这个:
var obj = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
var data = encodeURIComponent(JSON.stringify(obj));
// "%7B%22apple%22%3A%5B%7B%22kiwi%22%3A%22orange%22%7D%2C%7B%22banana%22%3A%22lemon%22%7D%5D%2C%22pear%22%3A%22passion%20fruit%22%7D"
var obj2 = JSON.parse(decodeURIComponent(data));
// {"apple":[{"kiwi":"orange"},{"banana":"lemon"}],"pear":"passion fruit"}
我已经为您制作了一个快速函数,它应该可以为您实现这一点,它将根据您的键=>值对创建参数并将您的非原始值字符串化。
var objToParams = function(obj){
var paramString = '';
for (var key in data) {
var value = obj[key];
if(obj[key] instanceof Array || obj[key] instanceof Object){
value = encodeURIComponent(JSON.stringify(value));
}
if (paramString != "") paramString += "&";
paramString += key + "=" + encodeURIComponent(value);
}
return paramString;
}
var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
console.log(objToParams(data));
编辑,根据您的评论,这应该有效,现在与 $.param:
的输出匹配
var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
var stringifyParam = function(data, topLevel, keyProp) {
var string = '';
for (var key in data) {
if(keyProp && topLevel[keyProp] ) {
if ( (topLevel[keyProp] instanceof Array&&topLevel[keyProp].indexOf(data[key])!==0) ) {
string += keyProp;
} else if ( (topLevel[keyProp] instanceof Object&&topLevel[keyProp][key]) ) {
string += keyProp;
}
}
if (typeof(topLevel[key])=='undefined') {
string += '[' + key + ']';
}
if (data[key] instanceof Array) {
string += stringifyParam(data[key], topLevel, key);
} else if(data[key] instanceof Object){
string += stringifyParam(data[key], topLevel, key);
} else {
if (typeof(topLevel[key])!='undefined') {
string += key;
}
string += '=' + data[key];
string += '&';
}
}
return string;
},
toParam = function(data){
var string = stringifyParam(data,data);
return encodeURI(string.substring(0,string.length-1).split(' ').join('+'));
};
console.log(toParam(data)); //apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit
console.log($.param(data)); //apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit
我正在尝试摆脱项目中的 jQuery 依赖项。该项目所做的一件事是像这样将数据发布到服务器:
var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
$.post( url, data);
感谢 You might not need jQuery,我知道如何使用 XMLHttpRequest
:
$.post
var request = new XMLHttpRequest();
request.open( 'POST', url, true);
request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send( data);
不幸的是,这个描述似乎假定 data
对象已经是一个 URL 编码的查询字符串,而在上面的例子中显然不是这样。事实证明 jQuery 的作用不止于此:对于给定的 data
对象,上面的 $.post
调用将首先将其转换为查询字符串,如下所示:
apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit
使用 XMLHttpRequest
的代码片段不会这样做,因此,服务器会向我抛出错误。
jQuery 也有一个很棒的方法调用 $.param
可以完成这种转换。如果我在最后一行使用
XMLHttpRequest
的代码片段将会非常有效
request.send( $.param(data));
但是,我并没有摆脱 jQuery 依赖。所以我正在寻找 $.param
的纯 Javascript 等价物。有人有类似的东西吗?
注意:问题Plain Javascript Equivalent of jQuery.param()问了一个类似的问题,但接受的答案只适用于非常简单的情况。将该答案中给出的函数应用于我上面的 data
对象会产生:
apple=%5Bobject%20Object%5D%2C%5Bobject%20Object%5D&pear=passion%20fruit
...这与上面给出的$.param(data)
的结果明显不同,并且由于它不能递归工作而丢失了信息。
您可以着手编写递归代码,但为什么不尝试简单的方案 JSON,这就是创建它的原因 - 以更简单的方式在客户端和服务器之间交换数据。
就这样做
request.send(JSON.stringify(data));
JSON.stringify
接受一个对象,然后将其转换为有效的 JSON,可以在服务器端解析。
要了解有关 JSON 的更多信息,没有比浏览它的标签摘录更好的方法了 here
您可以使用编码和解码 URIComponent 函数来完成此操作。
编辑
这个怎么样:
var qs = Object.keys(obj).reduce(function(a,k){
a.push(k+'='+encodeURIComponent(JSON.stringify(obj[k])));
return a;
},[]).join('&');
// "apple=%5B%7B%22kiwi%22%3A%22orange%22%7D%2C%7B%22banana%22%3A%22lemon%22%7D%5D&pear=%22passion%20fruit%22"
而不是这个:
var obj = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
var data = encodeURIComponent(JSON.stringify(obj));
// "%7B%22apple%22%3A%5B%7B%22kiwi%22%3A%22orange%22%7D%2C%7B%22banana%22%3A%22lemon%22%7D%5D%2C%22pear%22%3A%22passion%20fruit%22%7D"
var obj2 = JSON.parse(decodeURIComponent(data));
// {"apple":[{"kiwi":"orange"},{"banana":"lemon"}],"pear":"passion fruit"}
我已经为您制作了一个快速函数,它应该可以为您实现这一点,它将根据您的键=>值对创建参数并将您的非原始值字符串化。
var objToParams = function(obj){
var paramString = '';
for (var key in data) {
var value = obj[key];
if(obj[key] instanceof Array || obj[key] instanceof Object){
value = encodeURIComponent(JSON.stringify(value));
}
if (paramString != "") paramString += "&";
paramString += key + "=" + encodeURIComponent(value);
}
return paramString;
}
var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
console.log(objToParams(data));
编辑,根据您的评论,这应该有效,现在与 $.param:
的输出匹配var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
var stringifyParam = function(data, topLevel, keyProp) {
var string = '';
for (var key in data) {
if(keyProp && topLevel[keyProp] ) {
if ( (topLevel[keyProp] instanceof Array&&topLevel[keyProp].indexOf(data[key])!==0) ) {
string += keyProp;
} else if ( (topLevel[keyProp] instanceof Object&&topLevel[keyProp][key]) ) {
string += keyProp;
}
}
if (typeof(topLevel[key])=='undefined') {
string += '[' + key + ']';
}
if (data[key] instanceof Array) {
string += stringifyParam(data[key], topLevel, key);
} else if(data[key] instanceof Object){
string += stringifyParam(data[key], topLevel, key);
} else {
if (typeof(topLevel[key])!='undefined') {
string += key;
}
string += '=' + data[key];
string += '&';
}
}
return string;
},
toParam = function(data){
var string = stringifyParam(data,data);
return encodeURI(string.substring(0,string.length-1).split(' ').join('+'));
};
console.log(toParam(data)); //apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit
console.log($.param(data)); //apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit