如何将表单的所有元素转换为JavaScript对象?

我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;


当前回答

这是一个使用reduce的单行。Reduce是一个函数函数,它获取传递函数的返回值,并在下一次迭代中将其与列表中的第n个值一起传递回传递函数。

$('#formid').serializeArray().reduce((o,p) => ({...o, [p.name]: p.value}))

我们必须使用一些技巧来实现这一点:

…o(扩展语法)插入o中的所有键:值对包装我们在()中返回的对象,以将其与表示函数的{}区分开来将密钥(p.name)换行为[]

其他回答

如果使用Undercore.js,可以使用相对简洁的:

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

更现代的方法是将reduce与serializeArray()一起使用,方法如下:

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

这将有助于许多“正常”情况。

对于具有重复名称属性的多个标记的非常常见的实例,这是不够的。

由于具有重复名称属性的输入通常位于某些“包装器”(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>

可以使用reduce和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文档

【2020年更新】

在vanilla js中有一个简单的oneliner,它利用了fromEntries(一如既往,请检查浏览器支持):

Object.fromEntries(new FormData(form))

Tobias Cohen解决方案的固定版本。此函数正确处理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

不使用JQuery序列化深度嵌套表单

在花了几天时间寻找这个没有依赖关系的问题的解决方案之后,我决定使用FormDataAPI制作一个非jQuery表单数据序列化程序。

序列化程序中的逻辑很大程度上基于jQuery插件jQueryBBQ中的de-param函数,然而,在这个项目中,所有依赖项都被删除了。

这个项目可以在NPM和Github上找到:

https://github.com/GistApps/deep-serialize-form

https://www.npmjs.com/package/deep-serialize-form

function deepSerializeForm(form) {

  var obj = {};

  var formData = new FormData(form);

  var coerce_types = { 'true': !0, 'false': !1, 'null': null };

  /**
   * Get the input value from the formData by key
   * @return {mixed}
   */
  var getValue = function(formData, key) {

    var val = formData.get(key);

    val = val && !isNaN(val)              ? +val              // number
        : val === 'undefined'             ? undefined         // undefined
        : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
        : val;                                                // string

    return val;
  }

  for (var key of formData.keys()) {

    var val  = getValue(formData, key);
    var cur  = obj;
    var i    = 0;
    var keys = key.split('][');
    var keys_last = keys.length - 1;


    if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {

      keys[keys_last] = keys[keys_last].replace(/\]$/, '');

      keys = keys.shift().split('[').concat(keys);

      keys_last = keys.length - 1;

    } else {

      keys_last = 0;
    }


    if ( keys_last ) {

      for (; i <= keys_last; i++) {
        key = keys[i] === '' ? cur.length : keys[i];
        cur = cur[key] = i < keys_last
        ? cur[key] || (keys[i+1] && isNaN(keys[i+1]) ? {} : [])
        : val;
      }

    } else {

      if (Array.isArray(obj[key])) {

        obj[key].push( val );

      } else if (obj[key] !== undefined) {

        obj[key] = [obj[key], val];

      } else {

        obj[key] = val;

      }

    }

  }

  return obj;

}

window.deepSerializeForm = deepSerializeForm;