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

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


当前回答

不使用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;

其他回答

这里有一种非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;

})();

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

在不检查每个元素的情况下,确实无法做到这一点。您真正想知道的是“是否有其他人已经编写了一个将表单转换为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;
}

对于语义ui/formantic ui,有一个内置的行为get值:

const fields = $("#myForm.ui.form").form('get values');
const jsonStr = JSON.stringify(fields);

看见https://fomantic-ui.com/behaviors/form.html#/settings

get-values(标识符)返回与标识符数组匹配的元素值的对象。如果未通过IDS,将返回所有字段

另一个答案

document.addEventListener(“DOMContentLoaded”,函数(){setInterval(函数){var form=document.getElementById('form')||document.querySelector('form[name=“userprofile”]');var json=Array.from(new FormData(form)).map(函数(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>名称<input-type=“text”Name=“firstname”value=“John”/></p><p>姓氏<input name=“lastname”value=“Smith”/></p><p>工作<input name=“employment[name]”value=“inc,inc.”/></p><p>工作时间:<input name=“employment[since]”value=“2017”/></p><p>照片<input-type=“file”/></p><p>发送<input-type=“submit”/></p></form>JSON:<textarea id=“asJSON”></textarea>

表单数据:https://developer.mozilla.org/en-US/docs/Web/API/FormData