0

Been using jQuery for a while, but have been weaning myself off and typically only use it for $.ajax. I've also been planning on looking into XMLHttpRequest for some time, and thought today would be the day.

Everything has been straight forward except how to serialize non-primitive objects. Been spoiled with jQuery and just assumed this would be almost out of the box. Don't know if it matters, but I will primarily be posting to a PHP server. Also, I think I understand there is no standard format, and if so would lean towards how most frameworks do it.

My attempts are below (params2url1, params2url2, params2url3). The first and third attempt sends PHP [object Object] and the second attempt sends PHP strings "[1,2,3]" and "{"x":1,"y":"2","z":[3,2,1]}". I recognize I can deal with the strings server side, but don't think that is a good long term solution. I also don't want to depend on node.js as I've seen some recommend. I would rather either have my own function or use some super-lite 3rd party script.

The last attempt uses jQuery.params(), and while it works, it is dependent upon the jQuery library and as such is not an option.

I just tried using just JSON.stringify() as recommended by this highly voted answer https://stackoverflow.com/a/6418506/1032531 and it too does not work.

How is this best accomplished?

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>API Tester</title>
    </head>
    <body>
        <script>
            function params2url1(params) {
                return Object.keys(params).map(key => key + '=' + encodeURIComponent(params[key])).join('&');
            }
            function params2url2(params) {
                return Object.keys(params).map(key => key + '=' + encodeURIComponent(JSON.stringify(params[key]))).join('&');
            }
            function params2url3(params) {
                return Object.keys(params).map(key => key + '=' + encodeURIComponent(
                    typeof yourVariable === 'object' && yourVariable !== null?JSON.stringify(params[key]):params[key]
                )).join('&');
            }

            function ajax(stack) {
                if(stack.length===0) return;
                var request=stack.shift();

                var xhr = new XMLHttpRequest();
                var url='/test/params2url.php'+(request.method=='GET'?'?'+request.data:'');
                xhr.open(request.method, url, true);

                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
                xhr.responseType = request.responseType;

                xhr.onreadystatechange = function() {
                    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
                        console.log(request.method, request.test, xhr.response)
                        ajax(stack)
                    }
                }
                xhr.send(request.method=='GET'?null:request.data);
            }

            var params={a:123, b:'456', c:[1,2,3], d:{x:1,y:'2',z:[3,2,1]}};
            //var jqueryParms=$.params(params); //This works but requires jQUery
            var jqueryParms='123&b=456&c%5B%5D=1&c%5B%5D=2&c%5B%5D=3&d%5Bx%5D=1&d%5By%5D=2&d%5Bz%5D%5B%5D=3&d%5Bz%5D%5B%5D=2&d%5Bz%5D%5B%5D=1'
            ajax([
                {method:'GET', data: params2url1(params), responseType:'json', test:'params2url1'},
                {method:'POST', data: params2url1(params), responseType:'json', test:'params2url1'},
                {method:'GET', data: params2url2(params), responseType:'json', test:'params2url2'},
                {method:'POST', data: params2url2(params), responseType:'json', test:'params2url2'},
                {method:'GET', data: params2url3(params), responseType:'json', test:'params2url3'},
                {method:'POST', data: params2url3(params), responseType:'json', test:'params2url3'},
                {method:'GET', data: jqueryParms, responseType:'json', test:'jqueryParms'},
                {method:'POST', data: jqueryParms, responseType:'json', test:'jqueryParms'},
            ]);
        </script>
    </body>
</html>
user1032531
  • 24,767
  • 68
  • 217
  • 387

1 Answers1

0

With zero answers or comments, I expect there is a reason why I shouldn't be attempting to do this. That reason, however, totally escapes me and I would really appreciate any thoughts.

Should it be acceptable to send JavaScript objects to a PHP server, the following mimics jQuery's $.param, granted I haven't tested on multiple browsers. Would appreciate any positive or negative critiques.

function obj2url(params, key) {
    //Standalone replacement for jQuery's $.param()
    if(!key && Array.isArray(params)) {
        throw "obj2url cannot accept an array";
    }
    var parts=[];
    if(!key) key='';
    if(typeof params === 'object' && params != null) {
        if(Array.isArray(params)) {
            for (var i = 0; i < params.length; i++) {
                if(typeof params[i] === 'object' && params[i] != null) {
                    var subnode=obj2url(params[i], key===''?[]:key+'['+i+']');
                    parts.push(subnode);
                }
                else {
                    parts.push(encodeURIComponent((key===''?[]:key+'[]'))+'='+encodeURIComponent(params[i]));
                }
            }
        }
        else {
            for (var i in params) {
                if(typeof params[i] === 'object' && params[i] != null) {
                    var subnode=obj2url(params[i], key===''?i:key+'['+i+']');
                    parts.push(subnode);
                }
                else {
                    parts.push(encodeURIComponent((key===''?i:key+'['+i+']'))+'='+encodeURIComponent(params[i]));
                }
            }
        }
    }
    else {
        throw "obj2url cannot accept a string";
    }
    return parts.join('&');
}
user1032531
  • 24,767
  • 68
  • 217
  • 387