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

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


当前回答

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

其他回答

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

所以我使用了公认的答案,发现了一个主要缺陷。它不支持以下输入数组:

<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()的输出传递给它;否则它不会起作用。

像boss一样将表单转换为JSON


目前的来源是GitHub和Bower。

$bower安装jquery序列化对象


以下代码现已弃用。

以下代码可以处理所有类型的输入名称;按照你的预期处理它们。

例如:

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

此线程似乎已成为表单序列化的常见问题解答:)

我对PHP命名的看法:<input name=“user[name]”>

$('form').on('submit', function(ev) {
   ev.preventDefault();

   var obj = $(this).serializePHPObject();

   // $.post('./', obj);
});
(function ($) {
  // based on https://stackoverflow.com/a/25239999/1644202

  // <input name="user[name]" >
  $.fn.serializePHPObject = function () {
    var obj = {};
    $.each(this.serializeArray(), function (i, pair) {
      var cObj = obj,
        pObj,
        cpName;
      $.each(pair.name.split("["), function (i, pName) {
        pName = pName.replace("]", "");
        pObj = cObj;
        cpName = pName;
        cObj = cObj[pName] ? cObj[pName] : (cObj[pName] = {});
      });
      pObj[cpName] = pair.value;
    });
    return obj;
  };
})(jQuery);

使用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" />

And

<input type="text" name="zooAnimals[0].name" />