Отправьте традиционный объект JavaScript вместе с объектом jQuery в том же Ajax-запросе [duplicate]

Вы можете использовать эмулятор для этого. Взгляните на эту страницу: Android Emulator . Обратите внимание на следующие два аргумента:

  1. -netdelay & lt; delay & gt; Установите эмуляцию латентности сети на. Значение по умолчанию - нет. См. Таблицу в эмуляции сетевой задержки для поддерживаемых значений.
  2. -netspeed & lt; speed & gt; Установите эмуляцию сетевой скорости в. Значение по умолчанию заполнено. См. Таблицу в эмуляции сетевой скорости для поддерживаемых значений.

1446
задан 7 revs, 5 users 42% 24 April 2015 в 19:13
поделиться

30 ответов

serializeArray уже делает именно это. Вам просто нужно массировать данные в требуемый формат:

function objectifyForm(formArray) {//serialize data function

  var returnArray = {};
  for (var i = 0; i < formArray.length; i++){
    returnArray[formArray[i]['name']] = formArray[i]['value'];
  }
  return returnArray;
}

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

1544
ответ дан 11 revs, 10 users 55% 16 August 2018 в 01:02
поделиться
  • 1
    как говорит tvanfosson, зачем перебирать коллекцию дважды? – Yisroel 27 July 2009 в 17:15
  • 2
    Вы имеете в виду & quot; зачем использовать serializeArray для получения данных в первую очередь? & Quot; Поскольку serializeArray уже написан, он тестируется в нескольких браузерах и теоретически может быть улучшен в более поздних версиях jQuery. Чем меньше кода вы пишете, тем лучше для доступа к непоследовательным вещам, таким как элементы DOM, тем более стабильным будет ваш код. – Tobias Cohen 28 July 2009 в 04:05
  • 3
    Будьте осторожны, serializeArray () не будет включать отключенные элементы. Я часто отключаю элементы ввода, которые синхронизируются с другими элементами на странице, но я все же хочу, чтобы они были включены в мой сериализованный объект. Вам лучше использовать что-то вроде $.map( $("#container :input"), function(n, i) { /* n.name and $(n).val() */ } );, если вам нужно включить отключенные элементы. – Samuel Meacham 19 July 2010 в 00:54
  • 4
    @TobiasCohen Он не обрабатывает входные данные foo[bar] как ожидалось, не говоря уже о большинстве других разновидностей входных имен. После того, как я был очень расстроен неглубокими решениями этой проблемы, я в конечном итоге написал свой собственный плагин jQuery - подробности в ответе, который я дал этому вопросу. – maček 7 December 2011 в 22:13
  • 5
    @macek Я знаю, что это несколько месяцев, но с каких пор массивы используют нечисловые индексы? Никто не должен называть вход foo [bar] и надеяться рассматривать его как массив. Вы смешиваете массивы и хеши? Да, [] обычно понимается как аксессор, но не только для массивов. Также, говоря, что это допустимый HTML, но не в спецификации HTML, это противоречие. Да, браузер не может задушить его, но не многие веб-серверы будут знать, как десериализовать это, как и массив. Зачем? Потому что его не в спецификации HTML. Следовательно, это действительно неверно. – kroehre 8 September 2012 в 09:29

Мне нравится версия для самуллов, но я считаю, что у нее небольшая ошибка. Обычно JSON отправляется как

{"coreSKU": "PCGUYJS", "name_de": "whatever", ...

НЕ как

[{"coreSKU": "PCGUYJS"}, {"name_de": "whatever"}, ...

, поэтому функция IMO должна читать:

App.toJson = function( selector ) {
    var o = {};
    $.map( $( selector ), function( n,i )
    {
        o[n.name] = $(n).val();
    });     
    return o;
}

и обернуть его в массив данных (как и обычно ожидается), и, наконец, отправить его как astring App.stringify ({data: App.toJson ('#cropform: input')} )

Для строкового поиска в вопрос 3593046 для скудной версии, в json2.js для версии, покрываемой каждым событием. Это должно охватывать все это:)

17
ответ дан 2 revs 16 August 2018 в 01:02
поделиться
  • 1
    Я пробовал это в проекте, используя map, как это создает массив объектов с одним свойством, он не сворачивает все свойства в один объект. – joshperry 1 October 2010 в 23:46
  • 2
    отлично работает для меня (у меня довольно простая форма) – Frank Nocke 5 April 2011 в 11:21
  • 3
    крошечные, но важные исправления ниже, в моем ответе :) – Frank Nocke 5 April 2011 в 14:45
  • 4
    Из того, что я могу сказать, разница в том, что ваше решение не зависит от serializeArray, поэтому у вас есть свобода выбора любых входных данных, которые вы хотите (например, вы можете включать отключенные входы), правильно? То есть это не связано с какой-либо формой или событием отправки, это просто независимо само по себе? – dtgq 27 May 2016 в 01:12
  • 5
    единственная небольшая разница со связанным ответом заключается в том, что для создания экземпляра нет данных, reduce возвращает объект. Это не является независимым, так как toArray из jQuery. – juanpastas 27 May 2016 в 15:09
  • 6
    Спасибо. Это делает (как вы упомянули) крошечным, но очень важным отличием. – Adarsha 27 April 2018 в 18:00

Если вы используете Underscore.js , вы можете использовать относительно краткий:

_.object(_.map($('#myform').serializeArray(), _.values))
24
ответ дан 2 revs, 2 users 50% 16 August 2018 в 01:02
поделиться

Я сам кодировал форму для многомерного объекта JavaScript, чтобы использовать его в процессе производства. Результатом является https://github.com/serbanghita/formToObject.js .

3
ответ дан 2 revs, 2 users 67% 16 August 2018 в 01:02
поделиться
  • 1
    Я использовал вариацию этого для очень конкретной реализации, спасибо большое! – Chris Baker 19 December 2013 в 19:35
  • 2
    Спасибо, что сообщили мне, что это полезно. У меня есть некоторые входящие функции, чтобы катиться, и это мотивирует меня. – Șerban Ghiță 20 December 2013 в 10:50

Мне нравится использовать Array.prototype.reduce, потому что это однострочный, и он не полагается на Underscore.js или тому подобное:

$('#formid').serializeArray()
    .reduce(function(a, x) { a[x.name] = x.value; return a; }, {});

Это похоже к ответу с помощью Array.prototype.map, но вам не нужно загромождать область видимости дополнительной переменной объекта. Одноразовые покупки.

ВАЖНОЕ ПРИМЕЧАНИЕ. Формы со вставками, которые имеют повторяющиеся атрибуты name, являются допустимыми HTML и на самом деле являются общим подходом. Использование любого из ответов в этом потоке будет неуместным в этом случае (поскольку объектные ключи должны быть уникальными).

49
ответ дан 2 revs, 2 users 70% 16 August 2018 в 01:02
поделиться
  • 1
    Это довольно элегантно. Но стоит отметить, что array.prototype.reduce() недоступен в IE8, поскольку он является частью спецификации ECMAScript 5. Поэтому, если вам нужна поддержка IE8, вы захотите использовать polyfill или другое решение в целом. – gfullam 12 March 2015 в 15:02
  • 2
    Правда, но достаточно легко полиполивать. Кроме того, головная боль IE8 почти , благодаря отличной работе Microsoft с IE11 Enterprise Mode - я больше не обслуживаю отдельных пользователей с IE8, но когда организация с 10 000 сотрудников, все из которых используют IE8, ...это другое. К счастью, Microsoft много работает над этой проблемой. – Ethan Brown 12 March 2015 в 16:16
  • 3
    Я работаю в этой 10 000 сотрудников. – gfullam 12 March 2015 в 16:18
  • 4
    Ну, вам нужно, чтобы ваши ИТ-специалисты смотрели в режим IE11 Enterprise - он предоставляет современный браузер и способ запуска приложений, совместимых с IE8. Умное движение со стороны Microsoft: howtogeek.com/184634/… – Ethan Brown 12 March 2015 в 16:19
  • 5
    Отличный ответ! Простой и короткий! – Carlos Jimenez Bermudez 18 August 2016 в 20:56

Существует плагин, который делает это для jQuery, jquery.serializeJSON . Я успешно использовал его в нескольких проектах. Отлично работает.

4
ответ дан 2 revs, 2 users 71% 16 August 2018 в 01:02
поделиться

Если вы пытаетесь преобразовать все поля формы в JSON, чтобы отправить эту форму через Ajax, здесь добавлен плагин jQuery form .

4
ответ дан 2 revs, 2 users 75% 16 August 2018 в 01:02
поделиться
  • 1
    как вы получаете объект JSON с помощью этого плагина? – Yisroel 26 July 2009 в 20:38
  • 2
    Ну, если вам нужен только json, вы можете посмотреть на источник плагина, и есть функция formToArray (), которая выглядит как форма для преобразования json. Однако он не документирован в API. – serg 26 July 2009 в 21:48
  • 3
    Эта библиотека поддерживает только форматы urlencoded и multipart. Однако функция, упомянутая serg, может быть использована отдельно. – Tronic 22 July 2012 в 20:25

Использование:

function form_to_json (selector) {
  var ary = $(selector).serializeArray();
  var obj = {};
  for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value;
  return obj;
}

Выход:

{"myfield": "myfield value", "passwordfield": "mypasswordvalue"}
12
ответ дан 2 revs, 2 users 82% 16 August 2018 в 01:02
поделиться
  • 1
    хороший. простой, короткий и прямой – philip oghenerobo balogun 25 May 2016 в 13:37

Простота здесь лучше. Я использовал замену простой строки с регулярным выражением, и до сих пор они работали как шарм. Я не специалист по регулярному выражению, но я уверен, вы можете даже заполнить очень сложные объекты.

var values = $(this).serialize(),
attributes = {};

values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) {
    attributes[name] = value;
});
7
ответ дан 2 revs, 2 users 88% 16 August 2018 в 01:02
поделиться

Я нашел проблему с выбранным решением.

При использовании форм с именами на основе массива функция jQuery serializeArray () фактически умирает.

У меня есть фреймворк PHP, который использует имена полей на основе массива, чтобы одна и та же страница могла быть помещена на одну и ту же страницу несколько раз в нескольких представлениях. Это может быть удобно для добавления и редактирования и удаления на одной странице без противоречивых моделей форм.

Поскольку я хотел серализовать формы без необходимости использовать эту абсолютную базовую функциональность, я решил написать свою собственную seralizeArray ():

        var $vals = {};

        $("#video_edit_form input").each(function(i){
            var name = $(this).attr("name").replace(/editSingleForm\[/i, '');

            name = name.replace(/\]/i, '');

            switch($(this).attr("type")){
                case "text":
                    $vals[name] = $(this).val();
                    break;
                case "checkbox":
                    if($(this).attr("checked")){
                        $vals[name] = $(this).val();
                    }
                    break;
                case "radio":
                    if($(this).attr("checked")){
                        $vals[name] = $(this).val();
                    }
                    break;
                default:
                    break;
            }
        });

Обратите внимание: это также работает вне формы submit (), поэтому, если в остальной части вашего кода появляется ошибка, форма не будет отправлена, если вы поместите ссылку на кнопку говоря «сохранить изменения».

Также обратите внимание, что эту функцию никогда не следует использовать для проверки формы только для сбора данных для отправки на сервер для проверки. Использование такого слабого и массового кода приведет к XSS и т. Д.

3
ответ дан 2 revs, 2 users 95% 16 August 2018 в 01:02
поделиться

Другой ответ

document.addEventListener("DOMContentLoaded", function() {
  setInterval(function() {
    var form = document.getElementById('form') || document.querySelector('form[name="userprofile"]');
    var json = Array.from(new FormData(form)).map(function(e,i) {this[e[0]]=e[1]; return this;}.bind({}))[0];
    
    console.log(json)
    document.querySelector('#asJSON').value = JSON.stringify(json);
  }, 1000);
})
<form name="userprofile" id="form">
  <p>Name <input type="text" name="firstname" value="John"/></p>
  <p>Family name <input name="lastname" value="Smith"/></p>
  <p>Work <input name="employment[name]" value="inc, Inc."/></p>
  <p>Works since <input name="employment[since]" value="2017" /></p>
  <p>Photo <input type="file" /></p>
  <p>Send <input type="submit" /></p>
</form>

JSON: <textarea id="asJSON"></textarea>

FormData: https://developer.mozilla.org/en-US / документы / Web / API / FormData

2
ответ дан 2 revs, 2 users 98% 16 August 2018 в 01:02
поделиться

У меня была такая же проблема в последнее время и вышла с этим плагином jQuery jQuery , который преобразует форму в объект JSON с той же структурой. Это также чрезвычайно полезно для динамически создаваемых форм, где вы хотите, чтобы ваш пользователь добавлял больше полей в определенные места.

Суть в том, что вы действительно можете создать форму, чтобы она имела структуру, поэтому допустим, вы хотите создать форму, в которой пользователь вставляет свои любимые места в городе: вы можете представить эту форму для представления XML-элемента <places>...</places>, содержащего список мест, которым нравится пользователь, таким образом, список элементов <place>...</place>, каждый из которых содержит например, элемент <name>...</name>, элемент <type>...</type>, а затем список элементов <activity>...</activity> для представления действий, которые вы можете выполнять в таком месте. Таким образом, ваша структура XML будет выглядеть так:

<places>

    <place>

        <name>Home</name>
        <type>dwelling</type>

        <activity>sleep</activity>
        <activity>eat</activity>
        <activity>watch TV</activity>

    </place>

    <place>...</place>

    <place>...</place>

</places>

Как здорово было бы иметь объект JSON из этого, который будет представлять эту точную структуру, чтобы вы могли: либо

  • Сохраните этот объект, как он есть в любой CouchDB -подобной базе данных
  • Прочтите его со своей стороны на сервере $ _POST [] и извлеките правильно вложенный массив, может затем семантически манипулировать
  • Использовать сценарий на стороне сервера, чтобы преобразовать его в хорошо сформированный XML-файл (даже если вы не знаете его точной структуры a-priori)
  • Просто как-то использовать его, как он есть в любом Node.js -пользовательском скрипте сервера

ОК, так что теперь нам нужно подумать о том, как форма может представлять XML-файл.

Конечно, тег <form> - это root, но тогда у нас есть этот элемент <place>, который является контейнером, а не самим элементом данных, поэтому мы не можем использовать тег ввода для него.

Вот где тег <fieldset> пригодится! Мы будем использовать теги <fieldset> для представления всех элементов контейнера в нашем представлении формы / XML и поэтому получаем такой результат:

<form name="places">

    <fieldset name="place">

        <input type="text" name="name"/>
        <select name="type">
            <option value="dwelling">Dwelling</option>
            <option value="restoration">Restoration</option>
            <option value="sport">Sport</option>
            <option value="administrative">Administrative</option>
        </select>

        <input type="text" name="activity"/>
        <input type="text" name="activity"/>
        <input type="text" name="activity"/>

    </fieldset>

</form>

Как вы можете видеть в этой форме, мы нарушаем правило уникальных имен, но это нормально, потому что они будут преобразованы в массив элементов, поэтому на них будет ссылаться только их индекс внутри массива.

На этом этапе вы можете увидеть, как есть no name="array[]", как имя внутри формы, и все довольно, просто и семантично.

Теперь мы хотим, чтобы эта форма была преобразована в объект JSON, который будет выглядеть следующим образом:

{'places':{

    'place':[

        {

            'name': 'Home',
            'type': 'dwelling',

            'activity':[

                 'sleep',
                 'eat',
                 'watch TV'

            ]

        },

        {...},

        {...}

    ]

}}

Для этого я разработал этот плагин jQuery здесь , который кто-то помог оптимизировать в этот поток обзора кода и выглядит так:

$.fn.toJSO = function () {
    var obj = {},
        $kids = $(this).children('[name]');
    if (!$kids.length) {
        return $(this).val();
    }
    $kids.each(function () {
        var $el = $(this),
            name = $el.attr('name');
        if ($el.siblings("[name=" + name + "]").length) {
            if (!/radio|checkbox/i.test($el.attr('type')) || $el.prop('checked')) {
                obj[name] = obj[name] || [];
                obj[name].push($el.toJSO());
            }
        } else {
            obj[name] = $el.toJSO();
        }
    });
    return obj;
};

Я также сделал это одно сообщение в блоге , чтобы объяснить это больше.

Это преобразует все в форме в JSON (даже радио и флажки), и все, что вы оставите do is call

$.post('script.php',('form').toJSO(), ...);

Я знаю, что есть много способов конвертировать формы в объектах JSON и в большинстве случаев .serialize() и .serializeArray() работают отлично и в основном предназначены для использования, но я думаю, что вся эта идея записывает форму как структуру XML со значимыми именами и преобразует ее в хорошо сформированный объект JSON стоит попробовать, а также тот факт, что вы можете добавлять теги ввода с одним и тем же именем, не беспокоясь, очень полезно, если вам нужно извлечь динамически генерируемые данные форм.

Надеюсь, это помогает кому-то!

3
ответ дан 3 revs, 2 users 94% 16 August 2018 в 01:02
поделиться

Вы можете сделать это:

var frm = $(document.myform);
var data = JSON.stringify(frm.serializeArray());

См. JSON .

14
ответ дан 3 revs, 3 users 62% 16 August 2018 в 01:02
поделиться

Используя решение maček , я изменил его, чтобы работать с тем, как ASP.NET MVC обрабатывает свои вложенные / сложные объекты в одной и той же форме. Все, что вам нужно сделать, это изменить часть проверки на это:

"validate": /^[a-zA-Z][a-zA-Z0-9_]*((?:\[(?:\d*|[a-zA-Z0-9_]+)\])*(?:\.)[a-zA-Z][a-zA-Z0-9_]*)*$/,

Это будет соответствовать, а затем правильно отображать элементы с такими именами, как:

<input type="text" name="zooName" />

И

<input type="text" name="zooAnimals[0].name" />
6
ответ дан 4 revs, 2 users 78% 16 August 2018 в 01:02
поделиться

При всем заданном ответе есть какая-то проблема, которая ...

Если имя входа в качестве массива похожее на name[key], но оно будет генерироваться следующим образом

 name:{
   key : value
 }

Например: Если у меня есть такая форма.

    <form>
        <input name="name" value="value" >
        <input name="name1[key1]" value="value1" >
        <input name="name2[key2]" value="value2" >
        <input name="name3[key3]" value="value3" >
    </form>

Затем он будет генерировать объект таким образом со всем данным ответом.

Object {
    name : 'value',
    name1[key1] : 'value1',
    name2[key2] : 'value2',
    name3[key3] : 'value3', 
}

Но он должен генерировать, как показано ниже, каждый хочет получить как это, как показано ниже.

Object {
    name : 'value',
    name1 : {
        key1 : 'value1'
    },
    name2 : {
        key2 : 'value2'
    },
    name3 : {
        key2 : 'value2'
    }
}

Затем попробуйте выполнить это ниже кода js.

(function($){
    $.fn.getForm2obj = function(){
        var _ = {},_t=this;
        this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);}
        this.b = function(k,v,a = 0){ if(a) eval(k+".push("+v+");"); else eval(k+"="+v+";"); };
        $.map(this.serializeArray(),function(n){
            if(n.name.indexOf('[') > -1 ){
                var keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g),le = Object.keys(keys).length,tmp = '_';
                $.map(keys,function(key,i){
                    if(key == ''){
                        eval("ale = Object.keys("+tmp+").length;");
                        if(!ale) _t.b(tmp,'[]');
                        if(le == (i+1)) _t.b(tmp,"'"+n['value']+"'",1);
                        else _t.b(tmp += "["+ale+"]",'{}');
                    }else{
                        _t.c(tmp += "['"+key+"']",'{}');
                        if(le == (i+1)) _t.b(tmp,"'"+n['value']+"'");
                    }
                });
            }else _t.b("_['"+n['name']+"']","'"+n['value']+"'");
        });
        return _;
    }
})(jQuery);
console.log($('form').getForm2obj());
<!DOCTYPE html><html><head>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <title>Convert form data to JavaScript object with jQuery</title>
</head>
<body>
    <form>
        <input name="name" value="value" >
        <input name="name1[key1]" value="value1" >
        <input name="name2[key2]" value="value2" >
        <input name="name3[key3]" value="value3" >
        <input type="checkbox" name="name4[]" value="1" checked="checked">
        <input type="checkbox" name="name4[]" value="2">
        <input type="checkbox" name="name4[]" value="3">
    </form>
</body></html>

11
ответ дан 7 revs, 2 users 90% 16 August 2018 в 01:02
поделиться
  • 1
    Этот ответ действительно касается упомянутого случая, но он не охватывает такие случаи, как checkbox [] или даже один [другой] [другой_one] – Leonardo Beal 14 February 2018 в 17:06
  • 2
    @LeonardoBeal я исправлю свои анны .. проверьте это сейчас ..! – Bhavik Hirani 27 February 2018 в 20:30

Преобразовать формы в JSON LIKE A BOSS


Источник тока находится на GitHub и bower.

$ bower install jquery- serialize-object


Следующий код теперь устарел.

Следующий код может работать со всеми типами имен ввода; и обрабатывать их так, как вы ожидали.

Например:

<!-- all of these will work! -->
<input name="honey[badger]" value="a">
<input name="wombat[]" value="b">
<input name="hello[panda][]" value="c">
<input name="animals[0][name]" value="d">
<input name="animals[0][breed]" value="e">
<input name="crazy[1][][wonky]" value="f">
<input name="dream[as][vividly][as][you][can]" value="g">
// output
{
  "honey":{
    "badger":"a"
  },
  "wombat":["b"],
  "hello":{
    "panda":["c"]
  },
  "animals":[
    {
      "name":"d",
      "breed":"e"
    }
  ],
  "crazy":[
    null,
    [
      {"wonky":"f"}
    ]
  ],
  "dream":{
    "as":{
      "vividly":{
        "as":{
          "you":{
            "can":"g"
          }
        }
      }
    }
  }
}

Использование

$('#my-form').serializeObject();

Колдовство (JavaScript)

(function($){
    $.fn.serializeObject = function(){

        var self = this,
            json = {},
            push_counters = {},
            patterns = {
                "validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
                "key":      /[a-zA-Z0-9_]+|(?=\[\])/g,
                "push":     /^$/,
                "fixed":    /^\d+$/,
                "named":    /^[a-zA-Z0-9_]+$/
            };


        this.build = function(base, key, value){
            base[key] = value;
            return base;
        };

        this.push_counter = function(key){
            if(push_counters[key] === undefined){
                push_counters[key] = 0;
            }
            return push_counters[key]++;
        };

        $.each($(this).serializeArray(), function(){

            // skip invalid keys
            if(!patterns.validate.test(this.name)){
                return;
            }

            var k,
                keys = this.name.match(patterns.key),
                merge = this.value,
                reverse_key = this.name;

            while((k = keys.pop()) !== undefined){

                // adjust reverse_key
                reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');

                // push
                if(k.match(patterns.push)){
                    merge = self.build([], self.push_counter(reverse_key), merge);
                }

                // fixed
                else if(k.match(patterns.fixed)){
                    merge = self.build([], k, merge);
                }

                // named
                else if(k.match(patterns.named)){
                    merge = self.build({}, k, merge);
                }
            }

            json = $.extend(true, json, merge);
        });

        return json;
    };
})(jQuery);
406
ответ дан 8 revs, 2 users 98% 16 August 2018 в 01:02
поделиться
  • 1
    Таким образом, это работает очень хорошо. Но это неправильно: он не возвращает JSON, как следует из названия. Вместо этого он возвращает литерал объекта. Кроме того, важно проверить hasOwnProperty, иначе ваши массивы имеют все, что связано с их прототипом, например: {numbers: [& quot; 1 & quot ;, & quot; 3 & quot ;, indexOf: function () {...}]} – frontendbeauty 29 December 2011 в 02:44
  • 2
    @frontendbeauty на самом деле, toJSON - это именно то, что спецификация говорит, что его следует называть: developer.mozilla.org/en/JSON#toJSON () _ method неудачное неправильное словосочетание. – Ryan Florence 23 May 2012 в 18:21
  • 3
    @Marek, я проверил здесь jsfiddle . Трюк состоит в том, чтобы правильно назвать ваш выбор. <select name="foo" multiple="multiple"> не будет работать ни в одном сценарии. Однако, если вы используете [], как в <select name="bar[]" multiple="multiple">, он будет работать просто отлично :) – maček 31 January 2013 в 20:14
  • 4
    Это решение должно быть сверху, поскольку оно касается проблемы вложенных ключей как имен элементов формы. – SquareCat 23 February 2014 в 02:34
  • 5
    +1 Это, безусловно, лучший ответ. – Tim Seguine 2 July 2014 в 14:07

Фиксированная версия решения Тобиаса Коэна. Это правильно обрабатывает значения фальши, такие как 0 и ''.

jQuery.fn.serializeObject = function() {
  var arrayData, objectData;
  arrayData = this.serializeArray();
  objectData = {};

  $.each(arrayData, function() {
    var value;

    if (this.value != null) {
      value = this.value;
    } else {
      value = '';
    }

    if (objectData[this.name] != null) {
      if (!objectData[this.name].push) {
        objectData[this.name] = [objectData[this.name]];
      }

      objectData[this.name].push(value);
    } else {
      objectData[this.name] = value;
    }
  });

  return objectData;
};

И версия CoffeeScript для удобства кодирования:

jQuery.fn.serializeObject = ->
  arrayData = @serializeArray()
  objectData = {}

  $.each arrayData, ->
    if @value?
      value = @value
    else
      value = ''

    if objectData[@name]?
      unless objectData[@name].push
        objectData[@name] = [objectData[@name]]

      objectData[@name].push value
    else
      objectData[@name] = value

  return objectData
96
ответ дан Daniel X Moore 16 August 2018 в 01:02
поделиться
  • 1
    В coffeescript первое, если блок можно сократить до value = @value ? '' – nzifnab 11 September 2012 в 00:23
  • 2
    И если вы пытаетесь упорядочить Rails-подобные формы, вы можете удалить корень элемента из сгенерированных ключей. Для этого я добавил новый параметр keyMap и следующую строку: key = if keyMap? then keyMap(@name) else @name. Теперь вы можете передать функцию отображения, например (name) -> name.match(/\[([^\]]+)]/)[1]. И тогда нужно будет изменить все последующие @name на key, конечно – Damir Zekić 19 October 2012 в 14:23
  • 3
    @ DamirZekić, если ваш корневой элемент был post, вы могли бы просто сделать $('form').serializeObject().post. Нет необходимости в фантастическом сопоставлении. – maček 20 December 2012 в 21:21
  • 4
    @ DamirZekić Что это за линия? if (!objectData[this.name].push) ?? – kittu 20 June 2017 в 18:10
  • 5
    @kittu Проверяет, есть ли objectData[this.name] метод push (грубо говоря, это массив). Если это массив, он подталкивает значение, если он не является массивом, он преобразует его в массив, так что несколько значений с одним и тем же ключом будут объединены с массивом. – Daniel X Moore 20 June 2017 в 22:09

Поверните что-нибудь в объект (не тестировалось модулем)

<script type="text/javascript">
string = {};

string.repeat = function(string, count)
{
    return new Array(count+1).join(string);
}

string.count = function(string)
{
    var count = 0;

    for (var i=1; i<arguments.length; i++)
    {
        var results = string.match(new RegExp(arguments[i], 'g'));
        count += results ? results.length : 0;
    }

    return count;
}

array = {};

array.merge = function(arr1, arr2)
{
    for (var i in arr2)
    {
        if (arr1[i] && typeof arr1[i] == 'object' && typeof arr2[i] == 'object')
            arr1[i] = array.merge(arr1[i], arr2[i]);
        else
            arr1[i] = arr2[i]
    }

    return arr1;
}

array.print = function(obj)
{
    var arr = [];
    $.each(obj, function(key, val) {
        var next = key + ": ";
        next += $.isPlainObject(val) ? array.print(val) : val;
        arr.push( next );
      });

    return "{ " +  arr.join(", ") + " }";
}

node = {};

node.objectify = function(node, params)
{
    if (!params)
        params = {};

    if (!params.selector)
        params.selector = "*";

    if (!params.key)
        params.key = "name";

    if (!params.value)
        params.value = "value";

    var o = {};
    var indexes = {};

    $(node).find(params.selector+"["+params.key+"]").each(function()
    {
        var name = $(this).attr(params.key),
            value = $(this).attr(params.value);

        var obj = $.parseJSON("{"+name.replace(/([^\[]*)/, function()
        {
            return '"'+arguments[1]+'"';
        }).replace(/\[(.*?)\]/gi, function()
        {
            if (arguments[1].length == 0)
            {
                var index = arguments[3].substring(0, arguments[2]);
                indexes[index] = indexes[index] !== undefined ? indexes[index]+1 : 0;

                return ':{"'+indexes[index]+'"';
            }
            else
                return ':{"'+escape(arguments[1])+'"';
        })+':"'+value.replace(/[\\"]/gi, function()
        {
            return "\\"+arguments[0]; 
        })+'"'+string.repeat('}', string.count(name, ']'))+"}");

        o = array.merge(o, obj);
    });

    return o;
}
</script>

Выход теста:

$(document).ready(function()
{
    console.log(array.print(node.objectify($("form"), {})));
    console.log(array.print(node.objectify($("form"), {selector: "select"})));
});

на

<form>
    <input name='input[a]' type='text' value='text'/>
    <select name='input[b]'>
        <option>select</option>
    </select>

    <input name='otherinput[c][a]' value='a'/>
    <input name='otherinput[c][]' value='b'/>
    <input name='otherinput[d][b]' value='c'/>
    <input name='otherinput[c][]' value='d'/>

    <input type='hidden' name='anotherinput' value='hidden'/>
    <input type='hidden' name='anotherinput' value='1'/>

    <input type='submit' value='submit'/>
</form>

будет выход:

{ input: { a: text, b: select }, otherinput: { c: { a: a, 0: b, 1: d }, d: { b: c } }, anotherinput: 1 }
{ input: { b: select } }
3
ответ дан eithed 16 August 2018 в 01:02
поделиться

Я бы не использовал это на реальном сайте из-за атак XSS и, вероятно, много других проблем, но вот краткий пример того, что вы могли бы сделать:

$("#myform").submit(function(){
    var arr = $(this).serializeArray();
    var json = "";
    jQuery.each(arr, function(){
        jQuery.each(this, function(i, val){
            if (i=="name") {
                json += '"' + val + '":';
            } else if (i=="value") {
                json += '"' + val.replace(/"/g, '\\"') + '",';
            }
        });
    });
    json = "{" + json.substring(0, json.length - 1) + "}";
    // do something with json
    return false;
});
1
ответ дан Jason Berry 16 August 2018 в 01:02
поделиться
  • 1
    Не могли бы вы обойти атаки XSS, сначала конвертируя их в объект JS, а не напрямую в строку? – dtgq 27 May 2016 в 01:16

Все эти ответы казались мне более верными. Есть что сказать, для простоты. Пока все ваши входы формы имеют атрибут атрибута имени, это должно работать только джим-денди.

$('form.myform').submit(function () {
  var $this = $(this)
    , viewArr = $this.serializeArray()
    , view = {};

  for (var i in viewArr) {
    view[viewArr[i].name] = viewArr[i].value;
  }

  //Do stuff with view object here (e.g. JSON.stringify?)
});
28
ответ дан Jeffrey Van Alstine 16 August 2018 в 01:02
поделиться
  • 1
    +1 для джим денди – jenson-button-event 8 December 2011 в 17:00
  • 2
    Не обрабатывает данные вложенной формы, поэтому ответы становятся более сложными. – frontendbeauty 29 December 2011 в 02:33
  • 3
    Отлично работает для меня. Просто нужно было хранить пары ключ-значение; стягивание, а затем сохранение в localStorage или cookie работало просто денди. – Greg Pettit 4 January 2013 в 00:10

Для быстрого, современного решения используйте плагин jQuery JSONify jQuery. Пример ниже приведен дословно из GitHub README.

<form id="myform">
    <label>Name:</label>
    <input type="text" name="name"/>
    <label>Email</label>
    <input type="text" name="email"/>
    <label>Password</label>
    <input type="password" name="password"/>
</form>

Запуск:

$('#myform').jsonify();

Производит:

{"name":"Joe User","email":"joe@example.com","password":"mypass"}
{"name":"Joe User","email":"joe@example.com","password":"mypass"}

Выполняет:

]

Если вы хотите сделать POST JQuery с этим объектом JSON:

$('#mybutton').click(function() {
    $.post('/api/user', JSON.stringify($('#myform').jsonify()));
}
2
ответ дан Jim Stewart 16 August 2018 в 01:02
поделиться

Я предпочитаю этот подход, потому что: вам не нужно перебирать более двух коллекций, вы можете получить доступ к вещам, отличным от «имя» и «значение», если вам нужно, и вы можете дезинфицировать свои ценности, прежде чем хранить их в объект (если у вас есть значения по умолчанию, которые вы не хотите хранить, например).

$.formObject = function($o) {
    var o = {},
        real_value = function($field) {
            var val = $field.val() || "";

            // additional cleaning here, if needed

            return val;
        };

    if (typeof o != "object") {
        $o = $(o);
    }

    $(":input[name]", $o).each(function(i, field) {
        var $field = $(field),
            name = $field.attr("name"),
            value = real_value($field);

        if (o[name]) {
            if (!$.isArray(o[name])) {
                o[name] = [o[name]];
            }

            o[name].push(value);
        }

        else {
            o[name] = value;
        }
    });

    return o;
}

Использовать так:

var obj = $.formObject($("#someForm"));

Проверено только в Firefox.

3
ответ дан kflorence 16 August 2018 в 01:02
поделиться

Что случилось с:

var data = {};
$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 
253
ответ дан mkschreder 16 August 2018 в 01:02
поделиться
  • 1
    @LayZee - если ничего не выбрано, зачем вам это нужно на заднем конце? если вы должны выбрать опцию, подтвердите ввод перед сериализацией. – Dementic 30 September 2014 в 16:24
  • 2
    если вы ничего не возвращаете, почему бы вам просто не использовать .each вместо .map? – azerafati 6 November 2014 в 11:14
  • 3
    Это так просто, потому что это супер наивно ... не обрабатывает флажки с тем же именем. Каждый раз, когда он будет переопределять отмеченный элемент перед ним. Для обеспечения правильной сериализации вам определенно потребуется некоторое определение типа ввода. – Joshua F. Rountree 8 April 2015 в 14:35
  • 4
    Если вы хотите использовать чистое решение jQuery, вы можете использовать var form = {}; $.each($(this).serializeArray(), function (i, field) { form[field.name] = field.value || ""; }); – tfmontague 31 May 2015 в 07:02
  • 5
    $(this).serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {}) – juanpastas 13 June 2015 в 21:19

самым простым и точным способом, который я нашел для этой проблемы, было использование bbq plugin или этого one (размер которого составляет около 0,5 КБ).

он также работает с многомерными массивами.

$.fn.serializeObject = function()
{
	return $.deparam(this.serialize());
};

5
ответ дан Roey 16 August 2018 в 01:02
поделиться

Эта функция должна обрабатывать многомерные массивы вместе с несколькими элементами с тем же именем.

Я использовал его уже пару лет:

jQuery.fn.serializeJSON=function() {
  var json = {};
  jQuery.map(jQuery(this).serializeArray(), function(n, i) {
    var _ = n.name.indexOf('[');
    if (_ > -1) {
      var o = json;
      _name = n.name.replace(/\]/gi, '').split('[');
      for (var i=0, len=_name.length; i<len; i++) {
        if (i == len-1) {
          if (o[_name[i]]) {
            if (typeof o[_name[i]] == 'string') {
              o[_name[i]] = [o[_name[i]]];
            }
            o[_name[i]].push(n.value);
          }
          else o[_name[i]] = n.value || '';
        }
        else o = o[_name[i]] = o[_name[i]] || {};
      }
    }
    else {
      if (json[n.name] !== undefined) {
        if (!json[n.name].push) {
          json[n.name] = [json[n.name]];
        }
        json[n.name].push(n.value || '');
      }
      else json[n.name] = n.value || '';      
    }
  });
  return json;
};
16
ответ дан Sergey Varlamov 16 August 2018 в 01:02
поделиться

Однострочный (без зависимостей, кроме jQuery), использует привязку фиксированного объекта для функции, переданной в метод map.

$('form').serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]

Что он делает?

"id=2&value=1&comment=ok" => Object { id: "2", value: "1", comment: "ok" }

подходит для прогрессивных веб-приложений (можно легко поддерживать как регулярное представление формы, так и запросы ajax)

11
ответ дан test30 16 August 2018 в 01:02
поделиться

Невозможно сделать это без изучения каждого из элементов. То, что вы действительно хотите знать, «кто-то еще уже написал метод, который преобразует форму в объект JSON?» Что-то вроде следующего должно работать - обратите внимание, что он даст вам только элементы формы, которые будут возвращены через POST (должно иметь имя). Это не проверено.

function formToJSON( selector )
{
     var form = {};
     $(selector).find(':input[name]:enabled').each( function() {
         var self = $(this);
         var name = self.attr('name');
         if (form[name]) {
            form[name] = form[name] + ',' + self.val();
         }
         else {
            form[name] = self.val();
         }
     });

     return form;
}
21
ответ дан tvanfosson 16 August 2018 в 01:02
поделиться
  • 1
    true, мне понравится плагин, который сделает это для меня. ограничение наличия имени не имеет большого значения. будет ли это вытягивать все поля в форме, включая текстовые области и выбирает? – Yisroel 26 July 2009 в 15:02
  • 2
    не уверены, хотите ли вы указать [disabled], но я не думаю, что это нужно отправить / подобрать. – meder omuraliev 26 July 2009 в 15:06
  • 3
    может быть проще использовать serializeArray () для получения карты, а затем использовать код, аналогичный приведенному выше, чтобы преобразовать его в обычный объект JSON, таким образом я не имею дело с самой формой – Yisroel 26 July 2009 в 15:10
  • 4
    Использование serializedArray будет работать, но по существу вы будете повторять сборку дважды - один раз, чтобы создать массив, а затем по массиву. Я не вижу в этом необходимости. – tvanfosson 26 July 2009 в 15:50
  • 5
    Я настрою селектор для включения / отключения. – tvanfosson 26 July 2009 в 15:51

Я нашел проблему с кодом Тобиаса Коэна (у меня недостаточно очков, чтобы прокомментировать это напрямую), что в противном случае работает для меня. Если у вас есть два варианта выбора с тем же именем, оба со значением = "", исходный код будет генерировать «имя»: «» вместо «name»: ["", ""]

I подумайте, что это можно исправить добавлением «|| o [this.name] == ''" к первому условию if:

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] || o[this.name] == '') {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};
4
ответ дан user1134789 16 August 2018 в 01:02
поделиться

Из некоторого ответа старше :

$('form input,select').toArray().reduce(function(m,e){m[e.name] = $(e).val(); return m;},{})
17
ответ дан 2 revs 16 August 2018 в 01:02
поделиться
  • 1
    Я пробовал это в проекте, используя map, как это создает массив объектов с одним свойством, он не сворачивает все свойства в один объект. – joshperry 1 October 2010 в 23:46
  • 2
    отлично работает для меня (у меня довольно простая форма) – Frank Nocke 5 April 2011 в 11:21
  • 3
    крошечные, но важные исправления ниже, в моем ответе :) – Frank Nocke 5 April 2011 в 14:45
  • 4
    Из того, что я могу сказать, разница в том, что ваше решение не зависит от serializeArray, поэтому у вас есть свобода выбора любых входных данных, которые вы хотите (например, вы можете включать отключенные входы), правильно? То есть это не связано с какой-либо формой или событием отправки, это просто независимо само по себе? – dtgq 27 May 2016 в 01:12
  • 5
    единственная небольшая разница со связанным ответом заключается в том, что для создания экземпляра нет данных, reduce возвращает объект. Это не является независимым, так как toArray из jQuery. – juanpastas 27 May 2016 в 15:09
17
ответ дан 2 revs 6 September 2018 в 00:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: