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

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


当前回答

要获得快速、现代的解决方案,请使用JSONify jQuery插件。下面的示例是从GitHub README中逐字摘录的。这一切都归功于插件作者Kushal Pandya。

鉴于:

<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":"joe@example.com","password":"mypass"}

如果要使用此JSON对象执行jQuery POST:

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

其他回答

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

这和你想要的完全一样

仅执行以下代码一次

$.fn.serializeObject = function(){
    let d={};
    $(this).serializeArray().forEach(r=>d[r.name]=r.value);
    return d;
}

现在您可以多次执行以下行

let formObj = $('#myForm').serializeObject();
// will return like {id:"1", username:"abc"}

我的库phery中的代码有一个序列化例程,可以处理非常复杂的表单(如演示中所示https://github.com/pocesar/phery/blob/master/demo.php#L1664),而且不是一刀切。它实际上检查每个字段的类型。例如,单选框与范围不同,与keygen不同,与select multiple不同。我的功能涵盖了这一切,你可以看到它在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;
}

它是我的库phery的一部分,但可以移植到您自己的项目中。它在应该有数组的地方创建数组,从select、normalize复选框等选项中获取正确的选择选项。如果要将其转换为JSON(真正的JSON字符串),只需执行JSON.stringify($('form').serializeForm());

我检查了所有其他答案是否存在问题,如果输入名称是数组,例如name[key],那么应该这样生成:

名称:{key:value}


例如:如果您的HTML表单与下面的表单类似:

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

但是它应该像下面的JSON一样生成,而不是像下面这样的对象和所有其他答案。因此,如果有人想带来类似以下JSON的内容,请尝试下面的JS代码。

{
    name  : 'value',
    name1 : { key1 : 'value1' },
    name2 : { key2 : 'value2' },
    name3 : { key2 : 'value2' }
}

$.fn.getForm2obj=函数(){var_={};$.map(this.serializeArray(),函数(n){常量键=n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);如果(按键长度>1){让tmp=_;pop=keys.pop();for(设i=0;i<keys.length,j=keys[i];i++){tmp[j]=(!tmp[j]?(pop=='')?[]:{}:tmp[j]),tmp=tmp[j];}如果(pop=='')tmp=(!Array.isArray(tmp)?[]:tmp)、tmp.push(n.value);否则tmp[pop]=n.value;}else_[keys.pop()]=n.value;});返回_;}console.log($('form').getForm2obj());$('form input').change(函数(){console.clear();console.log($('form').getForm2obj());});<script src=“https://code.jquery.com/jquery-3.2.1.min.js“></script><表单><input name=“name”value=“value”><input type=“checkbox”name=“name1[]”value=“1”checked=“checked”>1<input type=“checkbox”name=“name1[]”value=“2”>2<input-type=“checkbox”name=“name1[]”value=“3”>3<br><input-type=“radio”name=“gender”value=“male”checked=“checked”>男性<input-type=“radio”name=“gender”value=“female”>女性<input name=“name2[key1]”value=“value1”><input name=“一个[另一个][另一个]”value=“value4”><input name=“name3[1][name]”value=“value4”><input name=“name3[2][name]”value=“value4”><input name=“[]”value=“value5”></form>