Преобразование данных формы в объект JavaScript с помощью jQuery

Как мне преобразовать все элементы моей формы в объект JavaScript?

Я хотел бы иметь какой-то способ автоматического построения объекта JavaScript из моей формы, без необходимости циклически перебирать каждый элемент. Я не хочу, чтобы строка возвращалась $('#formid').serialize();, и при этом я не хочу, чтобы карта возвращалась$('#formid').serializeArray();

26.07.2009 13:39:54
потому что первый возвращает строку, точно так же, как если бы вы отправили форму с помощью метода GET, а второй - массив объектов, каждый из которых имеет пару имя-значение. Я хочу, чтобы, если у меня было поле с именем «email», я получал объект, который позволит мне получить это значение с помощью obj.email. С serializeArray () мне нужно было бы сделать что-то вроде obj [indexOfElement] .value
Yisroel 26.07.2009 14:05:15
@James - Принятый ответ с использованием библиотеки Д. Крокфорда JSON-js. Вот пример: github.com/tleese22/google-app-engine-jappstart/blob/master/src/…
Taylor Leese 22.12.2010 20:11:55
@ Тейлор Да, я бы сказал, что в правильном ответе используется функция Крокфорда "lib" и "Tobias", например: JSON.stringify ($ ('myForm'). SerializeObject ())
James McCormack 23.12.2010 12:30:37
@Jonz - Есть и другие причины, помимо отправки / передачи для использования элемента формы. Если вы выполняете тяжелую работу со значениями форм в JavaScript (например, одностраничное приложение), очень удобно иметь их в объектном формате для доступа и манипулирования ими. Кроме того, строки запросов HTTP Post и Get - не единственные форматы для перемещения данных.
Patrick M 9.07.2012 14:11:02
Хороший js, с которым я столкнулся >> github.com/marioizquierdo/jquery.serializeJSON
Bongs 2.03.2013 21:56:35
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;
}

Остерегайтесь скрытых полей, имена которых совпадают с реальными входными данными, поскольку они будут перезаписаны.

1653
19.04.2017 05:41:59
как говорит tvanfosson, зачем перебирать коллекцию дважды?
Yisroel 27.07.2009 16:15:05
Вы имеете в виду "зачем использовать serializeArray для получения данных?" Поскольку serializeArray уже написан, он тестируется в нескольких браузерах и теоретически может быть улучшен в более поздних версиях jQuery. Чем меньше кода, который вы пишете для прямого доступа к несовместимым элементам, таким как элементы DOM, тем стабильнее будет ваш код.
Tobias Cohen 28.07.2009 03:05:06
Имейте в виду, что serializeArray () не будет включать отключенные элементы. Я часто отключаю элементы ввода, которые синхронизируются с другими элементами на странице, но я все еще хочу, чтобы они были включены в мой сериализованный объект. Вам лучше использовать что-то вроде, $.map( $("#container :input"), function(n, i) { /* n.name and $(n).val() */ } );если вам нужно включить отключенные элементы.
Samuel Meacham 18.07.2010 23:54:44
@TobiasCohen Он не обрабатывает foo[bar]входные данные -типа должным образом , не говоря уже о большинстве других разновидностей входных имен. Будучи очень разочарованным мелкими решениями этой проблемы, я закончил тем, что написал свой собственный плагин jQuery - подробности в ответе на этот вопрос.
maček 7.12.2011 20:13:45
@macek Я знаю, что это несколько месяцев, но с каких пор массивы используют нечисловые индексы? Никто не должен называть входные данные foo [bar] и надеяться рассматривать их как массив. Вы путаете массивы и хэши? Да, [] обычно понимается как метод доступа, а не только для массивов. Также говорят, что это действительный HTML, но не в спецификации HTML, противоречие. Да, браузер может не подавиться им, но не многие веб-серверы будут знать, как десериализовать это, как если бы они были массивом. Почему? Потому что его нет в спецификации HTML. Следовательно, это действительно недействительно.
kroehre 8.09.2012 08:29:18

Там действительно нет способа сделать это без изучения каждого из элементов. Что вы действительно хотите знать, так это «кто-то другой уже написал метод, который преобразует форму в объект 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;
}
23
26.07.2009 14:51:42
правда, я хотел бы плагин, который сделал бы это для меня. ограничение имени не имеет большого значения. будет ли это тянуть все поля в форме, включая textareas и select?
Yisroel 26.07.2009 14:02:46
Не уверен, что вы хотите, чтобы учесть [отключен], но я не думаю, что это следует отправить / забрать.
meder omuraliev 26.07.2009 14:06:32
может быть проще использовать serializeArray () для получения карты, а затем использовать код, аналогичный приведенному выше, для преобразования его в обычный объект JSON, так что я не имею дело с самой формой
Yisroel 26.07.2009 14:10:02
Использование serializedArray будет работать, но, по сути, вы будете выполнять итерацию по коллекции дважды: один раз для создания массива, затем для массива. Я не вижу в этом необходимости.
tvanfosson 26.07.2009 14:50:57
Я настрою селектор для включения / выключения.
tvanfosson 26.07.2009 14:51:30

Я бы не стал использовать это на живом сайте из-за 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
27.07.2009 03:04:23
Не могли бы вы обойти атаки XSS, сначала преобразовав их в объект JS, а не непосредственно в строку?
dvtan 27.05.2016 01:16:44

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

$.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
18.06.2010 22:47:30

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

Вот мой ответ на другой вопрос :

Изначально мы использовали serializeArray()метод jQuery , но он не включает отключенные элементы формы. Мы часто отключаем элементы формы, которые «синхронизируются» с другими источниками на странице, но нам все равно необходимо включить данные в наш сериализованный объект. Так serializeArray()вышло. Мы использовали :inputселектор, чтобы получить все входные элементы (как включенные, так и отключенные) в данном контейнере, а затем $.map()создать наш объект.

var inputs = $("#container :input");
var obj = $.map(inputs, function(n, i)
{
    var o = {};
    o[n.name] = $(n).val();
    return o;
});
console.log(obj);

Обратите внимание, что для этого каждому входу потребуется nameатрибут, который будет именем свойства результирующего объекта.

Это на самом деле немного изменилось по сравнению с тем, что мы использовали. Нам нужно было создать объект, который был структурирован как IDNET .NET, поэтому мы использовали это: (я предоставляю его здесь на случай, если это будет полезно)

var obj = $.map(inputs, function(n, i)
{
    return { Key: n.name, Value: $(n).val() };
});
console.log(obj);

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

17
23.05.2017 11:55:13
Я пробовал это в проекте, используя, mapкак это создает массив объектов с одним свойством, он не объединяет все свойства в один объект.
joshperry 1.10.2010 22:46:08

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

Я думаю, это можно исправить, добавив "|| 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;
};
6
3.03.2011 13:00:26

Исправленная версия решения Тобиаса Коэна. Это правильно обрабатывает ложные значения, такие как 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
103
31.12.2011 19:34:04
В coffeescript, что первый блок if может быть сокращен доvalue = @value ? ''
nzifnab 10.09.2012 23:23:24
И если вы пытаетесь сериализовать Rails-подобные формы, вы можете удалить корневой элемент из сгенерированных ключей. Чтобы достичь этого, я добавил новый параметр keyMapи следующую строку: key = if keyMap? then keyMap(@name) else @name. Теперь вы можете передать функцию отображения, как (name) -> name.match(/\[([^\]]+)]/)[1]. И тогда можно было бы необходимо изменить все последующие @nameдо key, конечно
Damir Zekić 19.10.2012 13:23:37
@ DamirZekić, если у вас есть корневой элемент post, вы можете просто сделать $('form').serializeObject().post. Нет необходимости в фантазии карт.
maček 20.12.2012 19:21:41
@ DamirZekić Что делает эта линия? if (!objectData[this.name].push)??
kittu 20.06.2017 18:10:18
@kittu Проверяет, objectData[this.name]есть ли метод push (грубо говоря, массив). Если это массив, он выталкивает значение, если это не массив, он преобразует его в массив, так что несколько значений с одним и тем же ключом будут объединены в массив.
Daniel X Moore 20.06.2017 22:09:31

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

$('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?)
});
30
31.03.2011 21:45:50
Однако не обрабатывает данные вложенных форм, поэтому ответы становятся более сложными.
frontendbeauty 29.12.2011 00:33:02
Отлично сработало для меня. Просто необходимо хранение пар ключ-значение; Стригизация, а затем сохранение в localStorage или cookie работало просто отлично.
Greg Pettit 3.01.2013 22:10:58

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

{ "coreSKU": "PCGUYJS", "name_de": "все", ...

НЕ как

[{ "CoreSKU": "PCGUYJS"}, { "name_de": "все"}, ...

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

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

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

Для stringify взгляда на вопросе 3593046 ненасыщенной версию, в json2.js для каждых-неожиданностей покрытой версии. Это должно покрыть все это :)

2
23.05.2017 12:18:27
Спасибо .. это делает (как вы упомянули) крошечную, но очень важную разницу.
Adarsha 27.04.2018 18:00:36

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

При использовании форм с именами на основе массива функция 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
24.04.2015 19:18:04

Функция serialize принимает объект JSON в качестве параметра и возвращает сериализацию String.

function serialize(object) {
            var _SPECIAL_CHARS = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, _CHARS = {
                '\b' : '\\b',
                '\t' : '\\t',
                '\n' : '\\n',
                '\f' : '\\f',
                '\r' : '\\r',
                '"' : '\\"',
                '\\' : '\\\\'
            }, EMPTY = '', OPEN_O = '{', CLOSE_O = '}', OPEN_A = '[', CLOSE_A = ']', COMMA = ',', COMMA_CR = ",\n", CR = "\n", COLON = ':', space = "", COLON_SP = ': ', stack = [], QUOTE = '"';
            function _char(c) {
                if (!_CHARS[c]) {
                    _CHARS[c] = '\\u' + ('0000' + (+(c.charCodeAt(0))).toString(16))
                        .slice(-4);
                }
                return _CHARS[c];
            }
            function _string(s) {
                return QUOTE + s.replace(_SPECIAL_CHARS, _char) + QUOTE;
                // return str.replace('\"','').replace('\"','');
            }

            function serialize(h, key) {
                var value = h[key], a = [], colon = ":", arr, i, keys, t, k, v;
                arr = value instanceof Array;
                stack.push(value);
                keys = value;
                i = 0;
                t = typeof value;
                switch (t) {
                    case "object" :
                        if(value==null){
                            return null;
                        }
                        break;
                    case "string" :
                        return _string(value);
                    case "number" :
                        return isFinite(value) ? value + EMPTY : NULL;
                    case "boolean" :
                        return value + EMPTY;
                    case "null" :
                        return null;
                    default :
                        return undefined;
                }
                arr = value.length === undefined ? false : true;

                if (arr) { // Array
                    for (i = value.length - 1; i >= 0; --i) {
                        a[i] = serialize(value, i) || NULL;
                    }
                }
                else { // Object
                    i = 0;
                    for (k in keys) {
                        if (keys.hasOwnProperty(k)) {
                            v = serialize(value, k);
                            if (v) {
                                a[i++] = _string(k) + colon + v;
                            }
                        }
                    }
                }

                stack.pop();
                if (space && a.length) {

                    return arr
                        ? "[" + _indent(a.join(COMMA_CR), space) + "\n]"
                        : "{\n" + _indent(a.join(COMMA_CR), space) + "\n}";
                }
                else {
                    return arr ? "[" + a.join(COMMA) + "]" : "{" + a.join(COMMA)
                        + "}";
                }
            }
            return serialize({
                "" : object
            }, "");
        }
0
16.10.2011 19:30:19

Конвертировать формы в JSON как босс


Текущий источник находится на 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);
445
29.11.2019 18:21:08
Итак, это работает довольно хорошо. Но он ошибочно назван: он не возвращает JSON, как следует из названия. Вместо этого он возвращает литерал объекта. Кроме того, важно проверить наличие hasOwnProperty, в противном случае в ваших массивах есть все, что связано с их прототипом, например: {numbers: ["1", "3", indexOf: function () {...}]}
frontendbeauty 29.12.2011 00:44:02
@frontendbeauty на самом деле, toJSON - это именно то, что в спецификации сказано, что его следует называть: developer.mozilla.org/en/JSON#toJSON()_method - неудачный неверный номер.
Ryan Florence 23.05.2012 17:21:16
@ Марек, я проверил здесь на jsfiddle . Хитрость заключается в том, чтобы правильно назвать ваш выбор. <select name="foo" multiple="multiple">не будет работать в любом сценарии. Однако, если вы используете [], как в <select name="bar[]" multiple="multiple">, он будет работать просто отлично :)
maček 31.01.2013 18:14:05
Хотел бы отметить, что github.com/serbanghita/formToObject - это аналогичный метод JavaScript (сторонние библиотеки не нужны), который выполняет ту же работу. Поддерживает «несколько», игнорирует «отключенные» элементы.
Șerban Ghiță 26.09.2013 22:22:41
Это решение должно быть на вершине, так как оно касается проблемы вложенных ключей как имен элементов формы.
SquareCat 23.02.2014 00:34:46

Превратите что-нибудь в объект (не проверенный на предмет юнитов)

<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
19.04.2012 13:07:55

Приведенное выше решение Тобиаса является правильным, однако, как отметил комментатор @macek, оно не обрабатывает вводы типа foo [bar] и не разделяет их на подобъекты.

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

Я просто изменил код Тобиаса выше, так что вся заслуга ему. Это, вероятно, можно сделать чище, но я просто взбил его за пять минут и подумал, что это может быть полезно.

В настоящее время он не обрабатывает многомерные массивы или числовые индексированные массивы. То есть он будет работать только с именами foo [bar], а не foo [].

jQuery.fn.serializeObjectPHP = function()
{
    var o = {};
    var re = /^(.+)\[(.*)\]$/;
    var a = this.serializeArray();
    var n;
    jQuery.each(a, function() {
        var name = this.name;
        if ((n = re.exec(this.name)) && n[2]) {
            if (o[n[1]] === undefined) {
                o[n[1]] = {};
                o[n[1]][n[2]] = this.value || '';
            } else if (o[n[1]][n[2]] === undefined) {
                o[n[1]][n[2]] = this.value || '';
            } else {
                if(!o[n[1]][n[2]].push) {
                    o[n[1]][n[2]] = [ o[n[1]][n[2]] ];
                }
                o[n[1]][n[2]].push(this.value || '');
            }
        } else {
            if (n && !n[2]) {
                name = n[1];
            }
            if (o[name] !== undefined) {
                if (!o[name].push) {
                    o[name] = [o[name]];
                }
                o[name].push(this.value || '');
            } else {
                o[name] = this.value || '';
            }
        }
    });
    return o;
};
0
26.04.2015 07:17:50
кажется, что вы не прочитали весь мой комментарий. Я разработал решение, которое обрабатывает foo[bar]вводы типа, а также foo[bar][bof][a][b][c][etc]; см мой ответ в этой теме. Также обратите внимание, что foo[bar]«синтаксический анализ» не является уникальным для PHP. Rails сильно полагается на это соглашение для передачи атрибутов формы объектам.
maček 22.05.2012 03:32:15

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

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

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
24.09.2012 19:18:13

Это улучшение функции Тобиаса Коэна, которая хорошо работает с многомерными массивами:

http://jsfiddle.net/BNnwF/2/

Однако, это не плагин jQuery, но потребуется всего несколько секунд, чтобы превратить его в один, если вы хотите использовать его таким образом: просто замените обертку объявления функции:

function serializeFormObject(form)
{
    ...
}

с:

$.fn.serializeFormObject = function()
{
    var form = this;
    ...
};

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

function serializeFormObject(form)
{
    function trim(str)
    {
        return str.replace(/^\s+|\s+$/g,"");
    }

    var o = {};
    var a = $(form).serializeArray();
    $.each(a, function() {
        var nameParts = this.name.split('[');
        if (nameParts.length == 1) {
            // New value is not an array - so we simply add the new
            // value to the result object
            if (o[this.name] !== undefined) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        }
        else {
            // New value is an array - we need to merge it into the
            // existing result object
            $.each(nameParts, function (index) {
                nameParts[index] = this.replace(/\]$/, '');
            });

            // This $.each merges the new value in, part by part
            var arrItem = this;
            var temp = o;
            $.each(nameParts, function (index) {
                var next;
                var nextNamePart;
                if (index >= nameParts.length - 1)
                    next = arrItem.value || '';
                else {
                    nextNamePart = nameParts[index + 1];
                    if (trim(this) != '' && temp[this] !== undefined)
                        next = temp[this];
                    else {
                        if (trim(nextNamePart) == '')
                            next = [];
                        else
                            next = {};
                    }
                }

                if (trim(this) == '') {
                    temp.push(next);
                } else
                    temp[this] = next;

                temp = next;
            });
        }
    });
    return o;
}
0
26.04.2015 07:22:49

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

Дело в том, что вы, возможно, захотите построить форму так, чтобы она имела саму структуру, поэтому предположим, что вы хотите создать форму, в которую пользователь вставляет свои любимые места в городе: вы можете представить, что эта форма представляет <places>...</places>элемент XML, содержащий список мест, которым пользователю нравится список <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-файл (даже если вы не знаете его точную структуру априори)
  • Просто используйте его как в любом серверном скрипте, похожем на 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>

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

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

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

{'places':{

    'place':[

        {

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

            'activity':[

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

            ]

        },

        {...},

        {...}

    ]

}}

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

$.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 (даже радио и флажки), и все, что вам нужно сделать, это позвонить

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

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

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

3
13.04.2017 12:40:37
Что ты пытаешься сделать?
Onheiron 2.09.2013 10:23:13

Мой код из моей библиотеки phery получил подпрограмму сериализации, которая может работать с действительно сложными формами (как в демонстрации https://github.com/pocesar/phery/blob/master/demo.php#L1664 ), и это не та -Размер подходит всем. Он фактически проверяет тип каждого поля. Например, радиоблок не совпадает с диапазоном, это не то же самое, что keygen, это не то же самое, что select множественный. Моя функция охватывает все это, и вы можете увидеть это по адресу https://github.com/pocesar/phery/blob/master/phery.js#L1851 .

serializeForm:function (opt) {
    opt = $.extend({}, opt);

    if (typeof opt['disabled'] === 'undefined' || opt['disabled'] === null) {
        opt['disabled'] = false;
    }
    if (typeof opt['all'] === 'undefined' || opt['all'] === null) {
        opt['all'] = false;
    }
    if (typeof opt['empty'] === 'undefined' || opt['empty'] === null) {
        opt['empty'] = true;
    }

    var
        $form = $(this),
        result = {},
        formValues =
            $form
                .find('input,textarea,select,keygen')
                .filter(function () {
                    var ret = true;
                    if (!opt['disabled']) {
                        ret = !this.disabled;
                    }
                    return ret && $.trim(this.name);
                })
                .map(function () {
                    var
                        $this = $(this),
                        radios,
                        options,
                        value = null;

                    if ($this.is('[type="radio"]') || $this.is('[type="checkbox"]')) {
                        if ($this.is('[type="radio"]')) {
                            radios = $form.find('[type="radio"][name="' + this.name + '"]');
                            if (radios.filter('[checked]').size()) {
                                value = radios.filter('[checked]').val();
                            }
                        } else if ($this.prop('checked')) {
                            value = $this.is('[value]') ? $this.val() : 1;
                        }
                    } else if ($this.is('select')) {
                        options = $this.find('option').filter(':selected');
                        if ($this.prop('multiple')) {
                            value = options.map(function () {
                                return this.value || this.innerHTML;
                            }).get();
                        } else {
                            value = options.val();
                        }
                    } else {
                        value = $this.val();
                    }

                    return {
                        'name':this.name || null,
                        'value':value
                    };
                }).get();

    if (formValues) {
        var
            i,
            value,
            name,
            $matches,
            len,
            offset,
            j,
            fields;

        for (i = 0; i < formValues.length; i++) {
            name = formValues[i].name;
            value = formValues[i].value;

            if (!opt['all']) {
                if (value === null) {
                    continue;
                }
            } else {
                if (value === null) {
                    value = '';
                }
            }

            if (value === '' && !opt['empty']) {
                continue;
            }

            if (!name) {
                continue;
            }

            $matches = name.split(/\[/);

            len = $matches.length;

            for (j = 1; j < len; j++) {
                $matches[j] = $matches[j].replace(/\]/g, '');
            }

            fields = [];

            for (j = 0; j < len; j++) {
                if ($matches[j] || j < len - 1) {
                    fields.push($matches[j].replace("'", ''));
                }
            }

            if ($matches[len - 1] === '') {
                offset = assign_object(result, fields, [], true, false, false);

                if (value.constructor === Array) {
                    offset[0][offset[1]].concat(value);
                } else {
                    offset[0][offset[1]].push(value);
                }
            } else {
                assign_object(result, fields, value);
            }
        }
    }

    return result;
}

Это часть моей библиотеки phery , но он может быть перенесен на свой собственный проект. Он создает массивы там, где должны быть массивы, получает правильные выбранные параметры из выбора, нормализует параметры флажков и т. Д. Если вы хотите преобразовать его в JSON (настоящая строка JSON), просто выполнитеJSON.stringify($('form').serializeForm());

0
26.04.2015 07:30:58
Переполнение стека не для продвижения вашей библиотеки.
Andrew Barber 7.12.2012 03:03:55
хорошо, но serializeFormэто часть моей библиотеки и делает именно то, что хочет ОП
pocesar 7.12.2012 03:12:38
Последняя строка самая лучшая
Alex78191 11.06.2017 20:56:04

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

       getData: function(element){
      //@todo may need additional logic for radio buttons
      var select = $(element).find('select');
      var input = $(element).find('input');
      var inputs = $.merge(select,input);
      var data = {};
      //console.log(input,'input');
      $.each(inputs,function(){
        if($(this).attr('type') != undefined){
          switch($(this).attr('type')){
            case 'checkbox':
              data[$(this).attr('name')] = ( ($(this).attr('checked') == 'checked') ? $(this).val():0 );
              break;
            default:
              data[$(this).attr('name')] = $(this).val();
              break;
          }
        }
        else{
          data[$(this).attr('name')] = $(this).val();
        }
      })
      return data;
   }
0
9.12.2012 18:47:51

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

var sf = $('#mainForm').serialize(); // URL encoded string
sf = sf.replace(/"/g, '\"');         // Be sure all "s are escaped
sf = '{"' + sf.replace(/&/g, '","'); // Start "object", replace tupel delimiter &
sf = sf.replace(/=/g, '":"') + '"}'; // Replace equal sign, add closing "object"

// Test the "object"
var formdata = eval("(" + sf + ")"); 
console.log(formdata);

Это работает как шарм, даже на очень сложных формах.

-7
26.04.2015 07:32:26
Это опасно для evalпользователя - все может случиться. Я настоятельно рекомендую не делать этого.
Thank you 18.02.2013 21:58:31

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

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

values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) {
    attributes[name] = value;
});
7
26.04.2015 07:33:20

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

var data = {};
$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 
283
22.07.2013 09:59:01
@LayZee - если ничего не выбрано, зачем вам это на заднем плане? если вы должны выбрать опцию, проверьте ввод перед сериализацией.
Dementic 30.09.2014 15:24:54
если вы ничего не возвращаете, почему бы вам просто не использовать .eachвместо .map??
azerafati 6.11.2014 10:14:02
Это так просто, потому что это супер наивно ... не обрабатывает флажки с тем же именем. Каждый раз он будет переопределять проверенный элемент перед ним. Вам определенно понадобится некоторое определение типа входа, чтобы убедиться, что оно правильно сериализовано.
Joshua F. Rountree 8.04.2015 14:35:41
Если вам нужно чистое решение jQuery, вы можете использоватьvar form = {}; $.each($(this).serializeArray(), function (i, field) { form[field.name] = field.value || ""; });
tfmontague 31.05.2015 07:02:40
$(this).serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {})
sites 13.06.2015 21:19:00

Для быстрого и современного решения используйте плагин 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"}

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

$('#mybutton').click(function() {
    $.post('/api/user', JSON.stringify($('#myform').jsonify()));
}
2
6.09.2013 18:38:01

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

3
26.04.2015 07:35:08
Я использовал вариант этого для очень конкретной реализации, большое спасибо!
Chris Baker 19.12.2013 17:35:50
Спасибо, что сообщили мне, что это полезно. У меня есть некоторые входящие функции, чтобы катиться, и это мотивирует меня.
Șerban Ghiță 20.12.2013 08:50:26

Я написал модуль jQuery, jsForm , который может сделать это двунаправленным даже для довольно сложных форм (допускает коллекции и другие более сложные структуры).

Он использует имя полей (плюс несколько специальных классов для коллекций) и соответствует объекту JSON. Позволяет автоматическую репликацию DOM-элементов для коллекций и обработки данных:

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="https://raw.github.com/corinis/jsForm/master/src/jquery.jsForm.js"></script>
        <script>
        $(function(){
            // Some JSON data
            var jsonData = {
                name: "TestName",   // Standard inputs
                description: "long Description\nMultiline", // Textarea
                links: [{href:'http://stackoverflow.com',description:'StackOverflow'}, {href:'http://www.github.com', description:'GitHub'}],   // Lists
                active: true,   // Checkbox
                state: "VISIBLE"    // Selects (enums)
            };

            // Initialize the form, prefix is optional and defaults to data
            $("#details").jsForm({
                data:jsonData
            });

            $("#show").click(function() {
                // Show the JSON data
                alert(JSON.stringify($("#details").jsForm("get"), null, " "));
            });
        });
        </script>
    </head>
    <body>
        <h1>Simpel Form Test</h1>
        <div id="details">
            Name: <input name="data.name"/><br/>
            <input type="checkbox" name="data.active"/> active<br/>
            <textarea name="data.description"></textarea><br/>
            <select name="data.state">
                <option value="VISIBLE">visible</option>
                <option value="IMPORTANT">important</option>
                <option value="HIDDEN">hidden</option>
            </select>
            <fieldset>
                <legend>Links</legend>
                <ul class="collection" data-field="data.links">
                    <li><span class="field">links.description</span> Link: <input name="links.href"/> <button class="delete">x</button></li>
                </ul>
            </fieldset>
            <button class="add" data-field="data.links">add a link</button><br/>
            Additional field: <input name="data.addedField"/>
        </div>
        <button id="show">Show Object</button>
    </body>
</html>
0
26.04.2015 07:37:57

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

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
26.04.2015 07:38:17

Используя решение Мачека , я изменил его, чтобы он работал так, как 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
23.05.2017 10:31:39

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

_.object(_.map($('#myform').serializeArray(), _.values))
23
26.04.2015 07:41:59

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

4
26.04.2015 07:43:09

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

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

Смотрите JSON .

15
16.02.2017 16:19:17