Как сериализовать непримитивный объект, используя только JavaScript - PullRequest
0 голосов
/ 17 ноября 2018

Я уже некоторое время использую jQuery, но отучаюсь от себя и обычно использую его только для $.ajax.Я также планировал изучить XMLHttpRequest в течение некоторого времени, и думал, что сегодня будет день.

Все было просто, кроме как сериализовать непримитивные объекты.Был испорчен jQuery и просто предположил, что это будет почти из коробки.Не знаю, имеет ли это значение, но я в первую очередь буду публиковать на сервер PHP.Кроме того, я думаю, что я понимаю, что стандартного формата не существует, и если это так, то он склоняется к тому, как это делают большинство фреймворков.

Мои попытки приведены ниже (params2url1, params2url2, params2url3).Первая и третья попытки отправляют PHP [object Object], а вторая попытка отправляет строки PHP "[1,2,3]" и "{"x":1,"y":"2","z":[3,2,1]}".Я понимаю, что могу иметь дело со строкой на стороне сервера, но не думаю, что это хорошее долгосрочное решение.Я также не хочу зависеть от node.js, как я видел некоторые рекомендации.Я бы предпочел либо иметь свою собственную функцию, либо использовать какой-нибудь сверхлегкий сторонний скрипт.

Последняя попытка использует jQuery.params(), и хотя она работает, она зависит от библиотеки jQuery и, как таковая, не являетсяoption.

Я только что попытался использовать JSON.stringify(), как рекомендовано в этом высоко голосуемом ответе https://stackoverflow.com/a/6418506/1032531, и он тоже не работает.

Как это лучше всего сделать?

<!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>

1 Ответ

0 голосов
/ 18 ноября 2018

С нулевыми ответами или комментариями, я ожидаю, что есть причина, почему я не должен пытаться сделать это.Эта причина, однако, полностью ускользает от меня, и я был бы очень признателен за любые мысли.

Если допустимо отправлять объекты JavaScript на PHP-сервер, то следующий код имитирует $ .param jQuery, учитывая, что я не тестировал нанесколько браузеров.Буду признателен за любую положительную или отрицательную критику.

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('&');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...