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

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


当前回答

我检查了所有其他答案是否存在问题,如果输入名称是数组,例如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>

其他回答

我的库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());

由于XSS攻击和可能存在的其他问题,我不会在现场网站上使用此功能,但下面是一个快速示例:

$("#myform").submit(function(){
    var arr = $(this).serializeArray();
    var json = "";
    jQuery.each(arr, function(){
        jQuery.each(this, function(i, val){
            if (i=="name") {
                json += '"' + val + '":';
            } else if (i=="value") {
                json += '"' + val.replace(/"/g, '\\"') + '",';
            }
        });
    });
    json = "{" + json.substring(0, json.length - 1) + "}";
    // do something with json
    return false;
});

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

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

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

我发现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;
};

这会把一切都考虑在内

函数formToObject(表单){let data=新FormData(表单);let queryString=新URLSearchParams(data).toString();var obj={};var params=queryString.split(“&”);对于(var i=0;i<params.length;i++){var param=params[i].split(“=”);var key=param[0].replace(“[]”,“”);var key=密钥.替换(“%5B%5 D”,“”);var值=参数[1];if(obj[key]==未定义){obj[key]=值;}else if(数组的obj[key]实例){obj[key].push(值);}其他{obj[key]=[obj[key],值];}}控制台日志(obj)返回obj;}<!DOCTYPE html><html><head><title>表单示例</title></head><body style=“height:800px;溢出:滚动”><form id=“test”onchange=“formToObject(this)”><div><h3>水果</h3><input type=“checkbox”name=“fruit”value=“apple”id=“apple“><label for=“apple”>Apfel</label><input-type=“checkbox”name=“fruit”value=“banana”id=“banana“><label for=“banana”>Banane</label><input type=“checkbox”name=“fruit”value=“cherry”id=“cherr”><label for=“cherry”>Kirsche</label><input type=“checkbox”name=“fruit”value=“葡萄”id=“葡萄”><label for=“葡萄”>Traube</label><input type=“checkbox”name=“fruit”value=“pear”id=“pear“><label for=“pear”>Birne</label></div><div><h3>多个选项</h3><select multiple name=“manyOptions[]”><option value=“选项1”>选项1</option><option value=“option 2”>选项2</option><option value=“选项3”>选项3</option></选择></div><div><h3>检查选项</h3><input type=“radio”name=“onceOption”value=“Option 1”>选项1<br><input type=“radio”name=“onceOption”value=“Option 2”>选项2<br><input type=“radio”name=“onceOption”value=“Option 3”>选项3<br></div></form></body></html>