简体   繁体   English

在Javascript中将对象文字编码为URL查询字符串

[英]Encode object literal as URL query string in Javascript

I am trying to get rid of the jQuery dependency in a project. 我试图摆脱项目中的jQuery依赖。 One thing that project does is posting data to a server like so: 项目的一件事是将数据发布到服务器,如下所示:

var data = {"apple": [{"kiwi": "orange"}, {"banana": "lemon"}], "pear": "passion fruit"};
$.post( url, data);

Thanks to You might not need jQuery , I know how to rewrite $.post in pure Javascript using XMLHttpRequest : 感谢您可能不需要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);

Unfortunately, this description seems to assume that the data object is already a URL-encoded query string, which is clearly not the case in the above example. 不幸的是,这个描述似乎假设data对象已经是URL编码的查询字符串,在上面的例子中显然不是这种情况。 It turns out jQuery does more than that: With the given data object, the above $.post call would first convert it to a query string, which would look like so: 事实证明,jQuery做的不止$.post :对于给定的data对象,上面的$.post调用首先会将其转换为查询字符串,如下所示:

apple%5B0%5D%5Bkiwi%5D=orange&apple%5B1%5D%5Bbanana%5D=lemon&pear=passion+fruit

The code snippet using XMLHttpRequest does not do so, and, thus, the server will throw errors at me. 使用XMLHttpRequest的代码片段不会这样做,因此服务器会向我抛出错误。

jQuery also has a wonderful method call $.param which does exactly this conversion. jQuery也有一个很好的方法调用$.param来完成这个转换。 The above code snippet using XMLHttpRequest will work marvelously if in the last line I do 如果在我的最后一行,使用XMLHttpRequest的上述代码片段将会非常有用

request.send( $.param(data));

But then, I did not get rid of the jQuery dependency. 但后来,我没有摆脱jQuery依赖。 So I'm looking for a pure Javascript equivalent of $.param . 所以我正在寻找相当于$.param的纯Javascript。 Does anyone have something like that? 有没有人有类似的东西?

Note: The question Plain Javascript Equivalent of jQuery.param() asks a similar question, but the accepted answer only works in very simple cases. 注意: jQuery.param()的Plain Javascript Equivalent问题提出了类似的问题,但是接受的答案仅适用于非常简单的情况。 Applying the function given in that answer to my above data object yields: 将该答案中给出的函数应用于我的上述data对象会产生:

apple=%5Bobject%20Object%5D%2C%5Bobject%20Object%5D&pear=passion%20fruit

...which is obviously different from the result of $.param(data) given above, and loses information since it doesn't work recursively. ...这显然不同于上面给出的$.param(data)的结果,并且因为它不能递归地工作而丢失信息。

I have made a quick function for you which should achieve this for you, it will create parameters from your key=>value pairs and stringify your non primitive values. 我为你做了一个快速的功能,它应该为你实现这个功能,它会从你的key => value对创建参数,并将你的非原始值字符串化。

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

http://jsfiddle.net/7buy3rjy/ http://jsfiddle.net/7buy3rjy/

Edit, from your comment this should work and is now matching the output of $.param: 编辑,从您的评论,这应该工作,现在匹配$ .param的输出:

http://jsfiddle.net/mg511z7w/ http://jsfiddle.net/mg511z7w/

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

You could go about doing recursive code but why not try the simple scheme JSON, which was why it was created - To exchange data between client and server in an easier manner. 你可以去做递归代码,但为什么不尝试简单的方案JSON,这就是创建它的原因 - 以更简单的方式在客户端和服务器之间交换数据。

Just do this 就这样做吧

request.send(JSON.stringify(data));

JSON.stringify accepts an Object which will then be converted to a valid JSON, which can be parsed in the server-side. JSON.stringify接受一个Object,然后将其转换为有效的JSON,可以在服务器端解析。

To know more about the JSON, there can't be a better way than going through it's tag excerpt here 要了解有关JSON的更多信息,除了通过此处的标记摘录之外,没有比这更好的方法

you could use encode and decode URIComponent functions to accomplish this. 您可以使用编码和解码URIComponent函数来完成此任务。

edit 编辑

what about this: 那这个呢:

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"

instead of this: 而不是这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM