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

1428

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

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

  • 0
    Я не понимаю, почему любой из этих методов достаточно для ваших нужд?
  • 15
    потому что первый возвращает строку, точно так же, как если бы вы отправили форму с помощью метода GET, а второй - массив объектов, каждый из которых имеет пару имя-значение. Я хочу, чтобы, если у меня было поле с именем «email», я получал объект, который позволит мне получить это значение с помощью obj.email. С serializeArray () я должен был бы сделать что-то вроде obj [indexOfElement] .value
Показать ещё 12 комментариев
Теги:
serialization

51 ответ

1662
Лучший ответ

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

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

  • 4
    как говорит tvanfosson, зачем повторять коллекцию дважды?
  • 66
    Вы имеете в виду "зачем использовать serializeArray для получения данных?" Поскольку serializeArray уже написан, он тестируется в нескольких браузерах и теоретически может быть улучшен в более поздних версиях jQuery. Чем меньше кода, который вы пишете для прямого доступа к несовместимым элементам, таким как элементы DOM, тем стабильнее будет ваш код.
Показать ещё 36 комментариев
447

Преобразование форм в 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);
  • 17
    Итак, это работает довольно хорошо. Но он ошибочно назван: он не возвращает JSON, как следует из названия. Вместо этого он возвращает объектный литерал. Кроме того, важно проверить наличие hasOwnProperty, в противном случае в ваших массивах есть все, что связано с их прототипом, например: {numbers: ["1", "3", indexOf: function () {...}]}
  • 1
    @frontendbeauty Было бы очень круто, если вы будете немного более откровенны или даже сделаете запрос на Github для этого (я не уверен, что вы имеете в hasOwnProperty замечанием hasOwnProperty )
Показать ещё 21 комментарий
266

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

var data = {};
$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 
  • 1
    Очень просто и эффективно, но как настроить учетную запись для групп радиостанций, в которых не выбрано радио?
  • 2
    @LayZee - если ничего не выбрано, зачем вам это на заднем плане? если вы должны выбрать опцию, проверьте ввод перед сериализацией.
Показать ещё 14 комментариев
106

Фиксированная версия решения Тобиаса Коэна. Он правильно обрабатывает значения фальши, такие как 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
  • 0
    В coffeescript, что первый блок if может быть сокращен до value = @value ? ''
  • 0
    И если вы пытаетесь сериализовать Rails-подобные формы, вы можете удалить корневой элемент из сгенерированных ключей. Для этого я добавил новый параметр keyMap и следующую строку: key = if keyMap? then keyMap(@name) else @name . Теперь вы можете передать функцию отображения как (name) -> name.match(/\[([^\]]+)]/)[1] . И тогда нужно будет изменить все последующие @name на key , конечно
Показать ещё 3 комментария
51

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

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

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

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

  • 0
    Это довольно элегантно. Но стоит отметить, что array.prototype.reduce() недоступна в IE8, поскольку она является частью спецификации ECMAScript 5. Поэтому, если вам нужна поддержка IE8, вам нужно использовать полифилл или другое решение в целом.
  • 3
    Правда, но это достаточно легко, чтобы заполнить. Кроме того, головная боль IE8 почти прекратилась благодаря отличной работе Microsoft с IE11 Enterprise Mode - я больше не обслуживаю отдельных пользователей с IE8, но когда приходит организация с 10000 сотрудников, которые все используют IE8 ... это совсем другое. К счастью, Microsoft усердно работает над этой проблемой.
Показать ещё 2 комментария
29

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

$('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?)
});
  • 0
    +1 за Джим Денди
  • 3
    Однако не обрабатывает данные вложенных форм, поэтому ответы становятся более сложными.
Показать ещё 1 комментарий
23

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

_.object(_.map($('#myform').serializeArray(), _.values))
21

Невозможно сделать это без изучения каждого из элементов. То, что вы действительно хотите знать, "кто-то еще уже написал метод, который преобразует форму в объект 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;
}
  • 0
    правда, я хотел бы плагин, который сделал бы это для меня. ограничение имени не имеет большого значения. будет ли это тянуть все поля в форме, включая textareas и select?
  • 0
    Не уверен, что вы хотите, чтобы учесть [отключено], но я не думаю, что это следует отправить / забрать.
Показать ещё 5 комментариев
17

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

Вот мой ответ из другого вопроса SO:

Вначале мы использовали метод jQuery serializeArray(), но это не включает в себя элементы формы, которые отключены. Мы часто будем отключать элементы формы, которые "синхронизируются" с другими источниками на странице, но нам все равно нужно включать данные в наш сериализованный объект. Итак, 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, который будет именем свойства результирующего объекта.

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

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

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

  • 6
    Я попробовал это в проекте, используя map как это создает массив объектов с одним свойством, он не объединяет все свойства в один объект.
  • 0
    хорошо работает для меня (у меня довольно простая форма)
Показать ещё 1 комментарий
16

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

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

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;
};
15

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

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

См. JSON.

13

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

Если введите имя как массив, например 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>
  • 0
    Этот ответ охватывает упомянутый случай, но он не охватывает такие случаи, как флажок [] или даже один [другой] [another_one]
  • 0
    @ LeonardoBeal я исправляю свои ответы .. проверь это сейчас ..!
12

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

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

Однострочный (без зависимостей, кроме 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)

7

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

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

values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) {
    attributes[name] = value;
});
6

Из более старого ответа:

$('form input, form select').toArray().reduce(function(m,e){m[e.name] = $(e).val(); return m;},{})
  • 0
    Из того, что я могу сказать, разница в том, что ваше решение не зависит от serializeArray поэтому у вас есть свобода выбора любых входов, которые вы хотите (например, вы можете включить отключенные входы), верно? Т.е. это не связано с какой-либо формой или событием отправки, это просто само по себе?
  • 0
    единственная небольшая разница со связанным ответом состоит в том, что нет никаких данных, необходимых для создания экземпляра, а reduce возвращает объект. Это не является независимым, так как toArray из jQuery.
6

Используя решение 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" />
5

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

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

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

Я нашел проблему с кодом Тобиаса Коэна (у меня недостаточно очков, чтобы прокомментировать это напрямую), что в противном случае работает для меня. Если у вас есть два варианта выбора с тем же именем, оба со значением = ", исходный код будет генерировать" имя ":" "вместо" 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;
};
4

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

4

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

3

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

  • 0
    Я использовал вариант этого для очень конкретной реализации, большое спасибо!
  • 0
    Спасибо, что сообщили мне, что это полезно. У меня есть некоторые входящие функции, чтобы катиться, и это мотивирует меня.
3

У меня была такая же проблема в последнее время и вышла с этот .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-like database
  • Прочитайте его со своей серверной стороны $_POST [] и извлеките правильно вложенный массив, который вы можете затем семантически манипулировать
  • Используйте некоторую серверную script, чтобы преобразовать ее в хорошо сформированный XML файл (даже если вы не знаете его точной структуры a-priori)
  • Просто как-то используйте его, как в любом Node.js-like server script

ОК, так что теперь нам нужно подумать, как форма может представлять 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 здесь, который кто-то помог оптимизировать этот код Просмотрите нить и выглядите так:

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

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

  • 0
    Это не похоже на работу для меня.
  • 0
    Что ты пытаешься сделать?
3

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

<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

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

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

Я предпочитаю этот подход, потому что: вам не нужно перебирать более двух коллекций, вы можете получить доступ к вещам, отличным от "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.

  • 0
    работает в хроме. +1
  • 0
    смешно работает с радиоприемниками.
2

Другой ответ

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/docs/Web/API/FormData

2

используя lodash # set

let serialized = [
  { key: 'data[model][id]', value: 1 },
  { key: 'data[model][name]', value: 'product' },
  { key: 'sid', value: 'dh0un1hr4d' }
];

serialized.reduce(function(res, item) {
  _.set(res, item.key, item.value);
  return res;
}, {});

// returns
{
  "data": {
    "model": {
      "id": 1,
      "name": "product"
    }
  },
  "sid": "dh0un1hr4d"
}
  • 0
    Мне нравится это решение, но оно не обрабатывает поля формы в формате массива key[] ; [ {key: 'items[]', value: 1 }, {key: 'items[]', value: 2 } ] приводит к { items: { "": 2 } } .
2

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

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

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

Мне нравится версия 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;
}

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

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

  • 0
    Спасибо .. это делает (как вы упомянули) крошечную, но очень важную разницу.
1

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

<input type="checkbox" name="array[]" value="1"/>
<input type="checkbox" name="array[]" value="2"/>
<input type="checkbox" name="array[]" value="3"/>

Это незначительное изменение должно исправить это:

function objectifyForm(inp){
    var rObject = {};
    for (var i = 0; i < inp.length; i++){
        if(inp[i]['name'].substr(inp[i]['name'].length - 2) == "[]"){
            var tmp = inp[i]['name'].substr(0, inp[i]['name'].length-2);
            if(Array.isArray(rObject[tmp])){
                rObject[tmp].push(inp[i]['value']);
            } else{
                rObject[tmp] = [];
                rObject[tmp].push(inp[i]['value']);
            }
        } else{
            rObject[inp[i]['name']] = inp[i]['value'];
        }
    }
    return rObject;
}

Не забудьте передать ему вывод из $(this).serializeArray();, иначе он не будет работать.

1

Если вы хотите преобразовать форму в объект javascript, то самым простым решением (в это время) является использование функциональных методов jQuery each и serializeArray.

$.fn.serializeObject = function() {

  var form = {};
  $.each($(this).serializeArray(), function (i, field) {
    form[field.name] = field.value || "";
  });

  return form;
};

Плагин размещен на GitHub:
https://github.com/tfmontague/form-object/blob/master/README.md

Может быть установлен с Bower:
bower install git://github.com/tfmontague/form-object.git

1

Если вы отправляете форму с JSON, вы должны удалить [] при отправке строки. Вы можете сделать это с помощью функции jQuery serializeObject():

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

$.fn.serializeObject = function() {
    var o = {};
    //var a = this.serializeArray();
    $(this).find('input[type="hidden"], input[type="text"], input[type="password"], input[type="checkbox"]:checked, input[type="radio"]:checked, select').each(function() {
        if ($(this).attr('type') == 'hidden') { //If checkbox is checked do not take the hidden field
            var $parent = $(this).parent();
            var $chb = $parent.find('input[type="checkbox"][name="' + this.name.replace(/\[/g, '\[').replace(/\]/g, '\]') + '"]');
            if ($chb != null) {
                if ($chb.prop('checked')) return;
            }
        }
        if (this.name === null || this.name === undefined || this.name === '')
            return;
        var elemValue = null;
        if ($(this).is('select'))
            elemValue = $(this).find('option:selected').val();
        else
            elemValue = this.value;
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(elemValue || '');
        }
        else {
            o[this.name] = elemValue || '';
        }
    });
    return o;
}
1

Я бы не использовал это на реальном сайте из-за атак 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;
});
  • 0
    Не могли бы вы обойти атаки XSS, сначала преобразовав их в объект JS, а не непосредственно в строку?
0
const formData = new FormData(form);

let formDataJSON = {};

for (const [key, value] of formData.entries()) {

    formDataJSON[key] = value;
}
0

Более современным способом является использование сокращения с помощью serializeArray() следующим образом:

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

Это поможет многим "нормальным" случаям.

Для очень распространенного экземпляра, где есть несколько тегов с атрибутами двойного name, этого недостаточно.

Поскольку входы с повторяющимися атрибутами name обычно находятся внутри некоторой "обертки" (div, ul, tr ,...), как в этом примере:

  <div class="wrapperClass">
    <input type="text" name="one">
    <input type="text" name="two">
  </div>
  <div class="wrapperClass">
    <input type="text" name="one">
    <input type="text" name="two">
  </div>

можно использовать сокращение с оператором map для итерации по ним:

$(".wrapperClass").map(function () {
  return $(this).find('*').serializeArray()
    .reduce((a, x) => ({ ...a, [x.name]: x.value }), {});
}).get();

Результатом будет массив объектов в формате:

  [
    {
      one: valueOfOne,
      two: valueOfTwo
    }, {
      one: valueOfOne,
      two: valueOfTwo
    }
  ]

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

0

Эта функция возвращает все значения, преобразованные в нужный тип;

bool/string/(целое число/поплавки)

Для этого вам нужно jQuery для этого, но так как serializeArray тоже jQuery, так что неважно, что это imho.

/**
 * serialized a form to a json object
 *
 * @usage: $("#myform").jsonSerialize();
 *
 */

(function($) {
    "use strict";
    $.fn.jsonSerialize = function() {
        var json = {};
        var array = $(this).serializeArray();
        $.each(array, function(key, obj) {
            var value = (obj.value == "") ? false : obj.value;
            if(value) {
                // check if we have a number
                var isNum = /^\d+$/.test(value);
                if(isNum) value = parseFloat(value);
                // check if we have a boolean
                var isBool = /^(false|true)+$/.test(value);
                if(isBool) value = (value!=="false");
            }
            json[obj.name] = value;
        });
        return json;
    }
})(jQuery);
0

Здесь не-jQuery:

    var getFormData = function(form) {
        //Ignore the submit button
        var elements = Array.prototype.filter.call(form.elements, function(element) {
            var type = element.getAttribute('type');
            return !type || type.toLowerCase() !== 'submit';
        });

Вы можете использовать его следующим образом:

function() {

    var getFormData = function(form) {
        //Ignore the submit button
        var elements = Array.prototype.filter.call(form.elements, function(element) {
            var type = element.getAttribute('type');
            return !type || type.toLowerCase() !== 'submit';
        });

        //Make an object out of the form data: {name: value}
        var data = elements.reduce(function(data, element) {
            data[element.name] = element.value;
            return data;
        }, {});

        return data;
    };

    var post = function(action, data, callback) {
        var request = new XMLHttpRequest();
        request.onload = callback;
        request.open('post', action);
        request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
        request.send(JSON.stringify(data), true);
        request.send();
    };

    var submit = function(e) {
        e.preventDefault();
        var form = e.target;
        var action = form.action;
        var data = getFormData(form);
        //change the third argument in order to do something
        //more intersting with the response than just print it
        post(action, data, console.log.bind(console));
    }

    //change formName below
    document.formName.onsubmit = submit;

})();
0

Мне приходилось бесстыдно самоподдерживать мою библиотеку форм.

transForm.js

Он делает такие вещи, как: сериализация, десериализация, очистка и отправка форм.

Причина, по которой я это сделал, это form2js/js2form не поддерживается и не так гибка и быстра, как хотелось бы. Мы используем его в производстве, потому что это form2js/js2form.

0

Недавно у меня была такая же проблема, поэтому я разработал функцию, которая позволяет анализировать элементы формы для получения идентификатора/значения управления и конвертировать его в JSON.

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

Вы можете найти полный script здесь.

Преимущество состоит в том, что он принимает только нужные вам данные, не перетаскивая весь объект.

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

Надеюсь, это поможет!

0

Используйте $('# formName'). serializeObject()

0

Я написал модуль 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

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

       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

Мой код из моей библиотеки phery получил процедуру сериализации, которая может обрабатывать действительно сложные формы (например, в демонстрационном https://github.com/pocesar/phery/blob/master/demo.php#L1664) и это не одноразовый. Он фактически проверяет, каков тип каждого поля. Например, радиоканал не совпадает с диапазоном, это не то же самое, что и keygen, это не то же самое, что выбрать несколько. Моя функция охватывает все это, и вы можете видеть он находится в 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;
}

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

  • 0
    Переполнение стека не для продвижения вашей библиотеки.
  • 3
    хорошо, но serializeForm является частью моей библиотеки и делает именно то, что хочет ОП
Показать ещё 1 комментарий
0

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

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

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

function serializeFormObject(form)
{
    ...
}

с:

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

Я думаю, это похоже на решение macek, поскольку оно делает то же самое, но я думаю, что это немного чище и проще. Я также включил входные данные теста 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

Решение Tobias выше верно, однако, как заметил комментатор @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
    кажется, что вы не прочитали весь мой комментарий. Я разработал решение, которое обрабатывает входные данные типа foo[bar] а также foo[bar][bof][a][b][c][etc] ; см мой ответ в этой теме. Также обратите внимание, что foo[bar] «синтаксический анализ» не является уникальным для PHP. Rails в значительной степени опирается на это соглашение для передачи атрибутов формы объектам.
0

Я не знаю, почему, но я нашел только одно действительно работающее решение для формы с входами с именами типа name="some[sub][sub][sub][name]".

Есть это: ССЫЛКА

0

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

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
            }, "");
        }
-2

Создайте карту и выполните цикл всех полей, сохранив их значения.

var params = {};
$("#form").find("*[name]").each(function(){
    params[this.getAttribute("name")] = this.value;
});
-2

Кто-нибудь упомянул ссылку ? довольно круто и так же просто, как $('# myform'). formParams();

-6

Используйте это:

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

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

  • 12
    eval пользовательский ввод рискованно - может случиться что угодно. Я настоятельно рекомендую не делать этого.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню