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

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


当前回答

好的,我知道这个问题已经有了一个高票的答案,但最近又有人问了一个类似的问题,我也被导向这个问题。我也想提供我的解决方案,因为它比公认的解决方案有一个优势:可以包含禁用的表单元素(这有时很重要,取决于UI的功能)

以下是我对另一个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。

其他回答

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

serialize函数将JSON对象作为参数并返回serialize 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
            }, "");
        }

另一个答案

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

我发现Tobias Cohen的代码有一个问题(我没有足够的分数来直接评论它),否则它对我来说是有效的。如果您有两个同名的选择选项,都是value=“”,原始代码将生成“name”:“”而不是“name”:[”,“”]

我认为这可以通过在第一个if条件中添加“||o[this.name]==''”来解决:

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

此函数应处理多维数组以及多个同名元素。

到目前为止,我已经使用了几年:

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