使用jQuery将表单数据转换为JavaScript对象

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

我想从我的表单中自动构建一个JavaScript对象,而不必遍历每个元素。我不想要$('#formid').serialize();返回的字符串,也不想要$('#formid').serializeArray();返回的映射

1073946 次浏览

如果不检查每个元素,真的没有办法做到这一点。你真正想知道的是“是否有其他人已经编写了一个将表单转换为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;}

由于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 jsonreturn false;});

序列化数组接口已经做到了这一点。你只需要将数据按摩成所需的格式:

function objectifyForm(formArray) {//serialize data functionvar returnArray = {};for (var i = 0; i < formArray.length; i++){returnArray[formArray[i]['name']] = formArray[i]['value'];}return returnArray;}

注意与实际输入同名的隐藏字段,因为它们会被覆盖。

我更喜欢这种方法,因为:你不必遍历2个集合,如果需要,你可以获得“名称”和“值”以外的东西,并且你可以在将值存储在对象中之前对它们进行清理(例如,如果你有不想存储的默认值)。

$.formObject = function($o) {var o = {},real_value = function($field) {var val = $field.val() || "";
// additional cleaning here, if needed
return val;};
if (typeof o != "object") {$o = $(o);}
$(":input[name]", $o).each(function(i, field) {var $field = $(field),name = $field.attr("name"),value = real_value($field);
if (o[name]) {if (!$.isArray(o[name])) {o[name] = [o[name]];}
o[name].push(value);}
else {o[name] = value;}});
return o;}

像这样使用:

var obj = $.formObject($("#someForm"));

仅在Firefox中测试。

好的,我知道这已经有了一个高度赞同的答案,但是最近又一个提出了类似的问题,我也被引导到这个问题。我也想提供我的解决方案,因为它提供了比公认解决方案的优势:你可以包含禁用的表单元素(这有时很重要,取决于你的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 IDicpedia的对象,所以我们使用了这个:(我在这里提供它,以防它有用)

var obj = $.map(inputs, function(n, i){return { Key: n.name, Value: $(n).val() };});console.log(obj);

我喜欢这两个解决方案,因为它们是$.map()函数的简单使用,并且您可以完全控制您的选择器(因此,您最终将哪些元素包含在结果对象中)。此外,不需要额外的插件。普通的旧jQuery。

我发现Tobias Cohen的代码有一个问题(我没有足够的点数直接评论它),它对我有用。如果你有两个同名的选择选项,都有值="",原始代码将产生"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;};

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 = @valueelsevalue = ''
if objectData[@name]?unless objectData[@name].pushobjectData[@name] = [objectData[@name]]
objectData[@name].push valueelseobjectData[@name] = value
return objectData

所有这些答案对我来说似乎都太过分了。为了简单起见,有一些话要说。只要您的所有表单输入都设置了name属性,这应该可以很好地工作。

$('form.myform').submit(function () {var $this = $(this), viewArr = $this.serializeArray(), view = {};
for (var i in viewArr) {view[viewArr[i].name] = viewArr[i].value;}
//Do stuff with view object here (e.g. JSON.stringify?)});

我喜欢samuels版本,但我相信它有一个小错误。通常JSON发送为

{"coreS KU":"PC GUY JS","name_de":"什么",…

不是作为

[{"coreS KU":"PC GUY JS"},{"name_de":"什么"},…

因此,海事组织的职能应为:

App.toJson = function( selector ) {var o = {};$.map( $( selector ), function( n,i ){o[n.name] = $(n).val();});return o;}

并将其包装在数据数组中(正如通常预期的那样),最后将其作为字符串发送App.stringify({data:App.toJson('#cropform:输入' )} )

对于stringify,精益版本在问题3593046,覆盖所有可能性的版本在json2.js。这应该涵盖了所有内容:)

我发现了所选解决方案的问题。

当使用具有基于数组的名称的表单时,jQuery序列化数组()函数实际上会死亡。

我有一个PHP框架,它使用基于数组的字段名称来允许在多个视图中多次将同一表单放入同一页面。这可以方便地将添加、编辑和删除放在同一页面上,而不会冲突表单模型。

因为我想对表单进行序列化而不必去掉这个绝对的基本功能,所以我决定编写自己的seralizeArray():

        var $vals = {};
$("#video_edit_form input").each(function(i){var name = $(this).attr("name").replace(/editSingleForm\[/i, '');
name = name.replace(/\]/i, '');
switch($(this).attr("type")){case "text":$vals[name] = $(this).val();break;case "checkbox":if($(this).attr("checked")){$vals[name] = $(this).val();}break;case "radio":if($(this).attr("checked")){$vals[name] = $(this).val();}break;default:break;}});

请注意:这也可以在表单提交()之外工作,因此如果代码的其余部分发生错误,如果您放置链接按钮说“保存更改”,表单将不会提交。

另请注意,此函数不应仅用于验证表单以收集要发送到服务器端进行验证的数据。使用这种弱且大量分配的代码将导致XSS等。

序列化函数将JSON对象作为参数并返回序列化字符串。

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) { // Arrayfor (i = value.length - 1; i >= 0; --i) {a[i] = serialize(value, i) || NULL;}}else { // Objecti = 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}, "");}

将表单转换为JSON像老板


当前源是在github鲍尔

安装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 keysif(!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_keyreverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// Pushif(k.match(patterns.push)){merge = self.build([], self.push_counter(reverse_key), merge);}
// Fixedelse if(k.match(patterns.fixed)){merge = self.build([], k, merge);}
// Namedelse if(k.match(patterns.named)){merge = self.build({}, k, merge);}}
json = $.extend(true, json, merge);});
return json;};})(jQuery);

将任何东西变成一个对象(不是单元测试)

<script type="text/javascript">string = {};
string.repeat = function(string, count){return new Array(count+1).join(string);}
string.count = function(string){var count = 0;
for (var i=1; i<arguments.length; i++){var results = string.match(new RegExp(arguments[i], 'g'));count += results ? results.length : 0;}
return count;}
array = {};
array.merge = function(arr1, arr2){for (var i in arr2){if (arr1[i] && typeof arr1[i] == 'object' && typeof arr2[i] == 'object')arr1[i] = array.merge(arr1[i], arr2[i]);elsearr1[i] = arr2[i]}
return arr1;}
array.print = function(obj){var arr = [];$.each(obj, function(key, val) {var next = key + ": ";next += $.isPlainObject(val) ? array.print(val) : val;arr.push( next );});
return "{ " +  arr.join(", ") + " }";}
node = {};
node.objectify = function(node, params){if (!params)params = {};
if (!params.selector)params.selector = "*";
if (!params.key)params.key = "name";
if (!params.value)params.value = "value";
var o = {};var indexes = {};
$(node).find(params.selector+"["+params.key+"]").each(function(){var name = $(this).attr(params.key),value = $(this).attr(params.value);
var obj = $.parseJSON("{"+name.replace(/([^\[]*)/, function(){return '"'+arguments[1]+'"';}).replace(/\[(.*?)\]/gi, function(){if (arguments[1].length == 0){var index = arguments[3].substring(0, arguments[2]);indexes[index] = indexes[index] !== undefined ? indexes[index]+1 : 0;
return ':{"'+indexes[index]+'"';}elsereturn ':{"'+escape(arguments[1])+'"';})+':"'+value.replace(/[\\"]/gi, function(){return "\\"+arguments[0];})+'"'+string.repeat('}', string.count(name, ']'))+"}");
o = array.merge(o, obj);});
return o;}</script>

测试的输出:

$(document).ready(function(){console.log(array.print(node.objectify($("form"), {})));console.log(array.print(node.objectify($("form"), {selector: "select"})));});

<form><input name='input[a]' type='text' value='text'/><select name='input[b]'><option>select</option></select>
<input name='otherinput[c][a]' value='a'/><input name='otherinput[c][]' value='b'/><input name='otherinput[d][b]' value='c'/><input name='otherinput[c][]' value='d'/>
<input type='hidden' name='anotherinput' value='hidden'/><input type='hidden' name='anotherinput' value='1'/>
<input type='submit' value='submit'/></form>

将产生:

{ input: { a: text, b: select }, otherinput: { c: { a: a, 0: b, 1: d }, d: { b: c } }, anotherinput: 1 }{ input: { b: select } }

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

此函数应处理多维数组以及具有相同名称的多个元素。

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

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函数的改进,它适用于多维数组:

但是,这不是一个jQuery插件,但如果您希望以这种方式使用它,只需几秒钟即可将其制作成一个:只需替换函数声明包装器:

function serializeFormObject(form){...}

有:

$.fn.serializeFormObject = function(){var form = this;...};

我想它类似于macek的解决方案,因为它做同样的事情,但我认为这有点干净和简单。我还将macek的测试用例输入包含到小提琴中,并添加了一些额外的输入。到目前为止,这对我来说效果很好。

function serializeFormObject(form){function trim(str){return str.replace(/^\s+|\s+$/g,"");}
var o = {};var a = $(form).serializeArray();$.each(a, function() {var nameParts = this.name.split('[');if (nameParts.length == 1) {// New value is not an array - so we simply add the new// value to the result objectif (o[this.name] !== undefined) {if (!o[this.name].push) {o[this.name] = [o[this.name]];}o[this.name].push(this.value || '');} else {o[this.name] = this.value || '';}}else {// New value is an array - we need to merge it into the// existing result object$.each(nameParts, function (index) {nameParts[index] = this.replace(/\]$/, '');});
// This $.each merges the new value in, part by partvar arrItem = this;var temp = o;$.each(nameParts, function (index) {var next;var nextNamePart;if (index >= nameParts.length - 1)next = arrItem.value || '';else {nextNamePart = nameParts[index + 1];if (trim(this) != '' && temp[this] !== undefined)next = temp[this];else {if (trim(nextNamePart) == '')next = [];elsenext = {};}}
if (trim(this) == '') {temp.push(next);} elsetemp[this] = next;
temp = next;});}});return o;}

我最近遇到了同样的问题,并提出了这个. toJSON jQuery插件,它将表单转换为具有相同结构的JSON对象。这对于动态生成的表单也特别有用,您希望让用户在特定位置添加更多字段。

关键是,您可能实际上想要构建一个表单,以便它本身具有结构,所以假设您想创建一个表单,用户在其中插入他最喜欢的地方:您可以想象这个表单表示一个<places>...</places> XML元素,其中包含用户喜欢的地方列表,因此一个<place>...</place>元素列表,每个元素都包含例如<name>...</name>元素、<type>...</type>元素,然后是<activity>...</activity>元素列表,以表示您可以在这样的地方执行的活动。所以您的XML结构如下所示:

<places>
<place>
<name>Home</name><type>dwelling</type>
<activity>sleep</activity><activity>eat</activity><activity>watch TV</activity>
</place>
<place>...</place>
<place>...</place>
</places>

如果有一个JSON对象来表示这个确切的结构,那该有多酷,这样你就可以:

  • 将此对象按原样存储在任何类似CouchDB的数据库中
  • 从$_POST[]服务器端读取它并检索一个正确嵌套的数组,然后您可以在语义上操作它
  • 使用一些服务器端脚本将其转换为格式良好的XML文件(即使您不知道它的确切结构)
  • 只需以某种方式使用它,就像在任何Node.js类服务器脚本中一样

好的,现在我们需要考虑表单如何表示XML文件。

当然,<form>标签是root,但是我们有<place>元素,它是一个容器而不是数据元素本身,所以我们不能为它使用输入标签。

这就是<fieldset>标签派上用场的地方!我们将使用<fieldset>标签来表示表单/XML表示中的所有容器元素,因此得到这样的结果:

<form name="places">
<fieldset name="place">
<input type="text" name="name"/><select name="type"><option value="dwelling">Dwelling</option><option value="restoration">Restoration</option><option value="sport">Sport</option><option value="administrative">Administrative</option></select>
<input type="text" name="activity"/><input type="text" name="activity"/><input type="text" name="activity"/>
</fieldset>
</form>

正如您在这个表单中看到的,我们打破了唯一名称的规则,但这没关系,因为它们将被转换为元素数组,因此它们将仅由数组内的索引引用。

在这一点上,你可以看到表单中没有像name="array[]"这样的名字,一切都很漂亮,简单和语义。

现在我们希望将此表单转换为JSON对象,如下所示:

{'places':{
'place':[
{
'name': 'Home','type': 'dwelling',
'activity':[
'sleep','eat','watch TV'
]
},
{...},
{...}
]
}}

为此,我开发了这个jQuery插件在这里,有人在这个代码审查线程中帮助优化,看起来像这样:

$.fn.toJSO = function () {var obj = {},$kids = $(this).children('[name]');if (!$kids.length) {return $(this).val();}$kids.each(function () {var $el = $(this),name = $el.attr('name');if ($el.siblings("[name=" + name + "]").length) {if (!/radio|checkbox/i.test($el.attr('type')) || $el.prop('checked')) {obj[name] = obj[name] || [];obj[name].push($el.toJSO());}} else {obj[name] = $el.toJSO();}});return obj;};

我还做了这一篇博客文章来解释这一点。

这将表单中的所有内容转换为JSON(甚至是无线电和复选框),您所要做的就是调用

$.post('script.php',('form').toJSO(), ...);

我知道有很多方法可以将表单转换为JSON对象,并且确保.serialize().serializeArray()在大多数情况下都能很好地工作,并且主要用于使用,但我认为将表单编写为具有有意义名称的XML结构并将其转换为格式良好的JSON对象的整个想法值得一试,如果您需要检索动态生成的表单数据,您可以添加同名输入标签而不用担心,这一事实非常有用。

我希望这能帮助别人!

我的库phery中的代码有一个序列化例程,可以处理非常复杂的表单(就像演示https://github.com/pocesar/phery/blob/master/demo.php#L1664中的那样),而且它不是万能的。它实际上检查每个字段的类型。例如,单选框与范围不同,与凯基不同,与选择多个不同。我的函数涵盖了这一切,你可以看到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) {vari,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的一部分,但它可以移植到您自己的项目中。它在应该有数组的地方创建数组,从选择、规范化复选框选项等中获取正确的选定选项。如果您想将其转换为JSON(真正的JSON字符串),只需执行JSON.stringify($('form').serializeForm());

此解决方案更好。此处的一些更流行的选项在未选中复选框时不正确处理复选框。

getData: function(element){//@todo may need additional logic for radio buttonsvar select = $(element).find('select');var input = $(element).find('input');var inputs = $.merge(select,input);var data = {};//console.log(input,'input');$.each(inputs,function(){if($(this).attr('type') != undefined){switch($(this).attr('type')){case 'checkbox':data[$(this).attr('name')] = ( ($(this).attr('checked') == 'checked') ? $(this).val():0 );break;default:data[$(this).attr('name')] = $(this).val();break;}}else {data[$(this).attr('name')] = $(this).val();}})return data;}

使用这个:

var sf = $('#mainForm').serialize(); // URL encoded stringsf = sf.replace(/"/g, '\"');         // Be sure all "s are escapedsf = '{"' + sf.replace(/&/g, '","'); // Start "object", replace tupel delimiter &sf = sf.replace(/=/g, '":"') + '"}'; // Replace equal sign, add closing "object"
// Test the "object"var formdata = eval("(" + sf + ")");console.log(formdata);

它就像一个魅力,即使在非常复杂的形式。

简单性在这里是最好的。我用一个简单的字符串替换正则表达式,到目前为止它们工作得很好。我不是正则表达式专家,但我敢打赌你甚至可以填充非常复杂的对象。

var values = $(this).serialize(),attributes = {};
values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) {attributes[name] = value;});

什么是错的:

var data = {};$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;});

要获得快速、现代的解决方案,请使用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()));}

我编写了一个jQuery模块jsForm,即使对于非常复杂的表单(也允许集合和其他更复杂的结构),它也可以双向执行此操作。

它使用字段的名称(加上一些用于集合的特殊类)并匹配JSON对象。它允许自动复制DOM元素以进行集合和数据处理:

<html><head><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><script src="https://raw.github.com/corinis/jsForm/master/src/jquery.jsForm.js"></script><script>$(function(){// Some JSON datavar jsonData = {name: "TestName",   // Standard inputsdescription: "long Description\nMultiline", // Textarealinks: [{href:'http://stackoverflow.com',description:'StackOverflow'}, {href:'http://www.github.com', description:'GitHub'}],   // Listsactive: true,   // Checkboxstate: "VISIBLE"    // Selects (enums)};
// Initialize the form, prefix is optional and defaults to data$("#details").jsForm({data:jsonData});
$("#show").click(function() {// Show the JSON dataalert(JSON.stringify($("#details").jsForm("get"), null, " "));});});</script></head><body><h1>Simpel Form Test</h1><div id="details">Name: <input name="data.name"/><br/><input type="checkbox" name="data.active"/> active<br/><textarea name="data.description"></textarea><br/><select name="data.state"><option value="VISIBLE">visible</option><option value="IMPORTANT">important</option><option value="HIDDEN">hidden</option></select><fieldset><legend>Links</legend><ul class="collection" data-field="data.links"><li><span class="field">links.description</span> Link: <input name="links.href"/> <button class="delete">x</button></li></ul></fieldset><button class="add" data-field="data.links">add a link</button><br/>Additional field: <input name="data.addedField"/></div><button id="show">Show Object</button></body></html>

用途:

function form_to_json (selector) {var ary = $(selector).serializeArray();var obj = {};for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value;return obj;}

输出:

{"myfield": "myfield value", "passwordfield": "mypasswordvalue"}

使用马切克溶液,我修改了它以处理ASP.NETMVC在同一表单上处理嵌套/复杂对象的方式。你所要做的就是将验证部分修改为:

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

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

如果你使用的是Underscore.js,你可以使用相对简洁的:

_.object(_.map($('#myform').serializeArray(), _.values))

有一个插件可以为jQueryjquery.serializeJSON做到这一点。我现在已经在几个项目中成功地使用了它。它就像一个魅力。

你可以这样做:

var frm = $(document.myform);var data = JSON.stringify(frm.serializeArray());

JSON

如果您使用JSON发送表单,您必须在发送字符串时删除[]。您可以使用jQuery函数序列化对象()做到这一点:

var frm = $(document.myform);var data = JSON.stringify(frm.serializeObject());
$.fn.serializeObject = function() {var o = {};//var a = this.serializeArray();$(this).find('input[type="hidden"], input[type="text"], input[type="password"], input[type="checkbox"]:checked, input[type="radio"]:checked, select').each(function() {if ($(this).attr('type') == 'hidden') { //If checkbox is checked do not take the hidden fieldvar $parent = $(this).parent();var $chb = $parent.find('input[type="checkbox"][name="' + this.name.replace(/\[/g, '\[').replace(/\]/g, '\]') + '"]');if ($chb != null) {if ($chb.prop('checked')) return;}}if (this.name === null || this.name === undefined || this.name === '')return;var elemValue = null;if ($(this).is('select'))elemValue = $(this).find('option:selected').val();elseelemValue = this.value;if (o[this.name] !== undefined) {if (!o[this.name].push) {o[this.name] = [o[this.name]];}o[this.name].push(elemValue || '');}else {o[this.name] = elemValue || '';}});return o;}

我喜欢使用Array.prototype.reduce,因为它是一行代码,它不依赖于Underscore.js或类似的代码:

$('#formid').serializeArray().reduce(function(a, x) { a[x.name] = x.value; return a; }, {});

这类似于使用Array.prototype.map的答案,但您不需要使用额外的对象变量来混淆您的范围。一站式购物。

重要说明:具有重复name属性的输入的表单是有效的超文本标记语言,实际上是一种常见的方法。在这种情况下,使用此线程中的任何答案都是不合适的(因为对象键必须是唯一的)。

如果您想将表单转换为javascript对象,那么最简单的解决方案(目前)是使用jQuery的eachserializeArray函数方法。

$.fn.serializeObject = function() {
var form = {};$.each($(this).serializeArray(), function (i, field) {form[field.name] = field.value || "";});
return form;};

托管在GitHub上的插件:
https://github.com/tfmontague/form-object/blob/master/README.md

可以使用Bowers安装:
bower install git://github.com/tfmontague/form-object.git

老年答案:

$('form input, form select').toArray().reduce(function(m,e){m[e.name] = $(e).val(); return m;},{})

这是一个非jQuery的方式:

    var getFormData = function(form) {//Ignore the submit buttonvar 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 buttonvar 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 itpost(action, data, console.log.bind(console));}
//change formName belowdocument.formName.onsubmit = submit;
})();

我为这个问题找到的最简单和最准确的方法是使用bbq插件或这个一个(大约0.5K字节大小)。

它也适用于多维数组。

$.fn.serializeObject = function(){return $.deparam(this.serialize());};

此函数返回转换为正确类型的所有值;

bool/string/(整数/浮点数)可能

虽然你有点需要jQuery,但由于序列化数组也是jQuery,所以没什么大不了的。

/*** serialized a form to a json object** @usage: $("#myform").jsonSerialize();**/
(function($) {"use strict";$.fn.jsonSerialize = function() {var json = {};var array = $(this).serializeArray();$.each(array, function(key, obj) {var value = (obj.value == "") ? false : obj.value;if(value) {// check if we have a numbervar isNum = /^\d+$/.test(value);if(isNum) value = parseFloat(value);// check if we have a booleanvar isBool = /^(false|true)+$/.test(value);if(isBool) value = (value!=="false");}json[obj.name] = value;});return json;}})(jQuery);

创建一个map并循环所有字段,保存它们的值。

var params = {};$("#form").find("*[name]").each(function(){params[this.getAttribute("name")] = this.value;});

使用Lodash#set

let serialized = [{ key: 'data[model][id]', value: 1 },{ key: 'data[model][name]', value: 'product' },{ key: 'sid', value: 'dh0un1hr4d' }];
serialized.reduce(function(res, item) {_.set(res, item.key, item.value);return res;}, {});
// returns{"data": {"model": {"id": 1,"name": "product"}},"sid": "dh0un1hr4d"}

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

name:{ key : value }


例如:如果你有一个类似于下面的超文本标记语言:

<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 = function() {var _ = {};$.map(this.serializeArray(), function(n) {const keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);if (keys.length > 1) {let tmp = _;pop = keys.pop();for (let i = 0; i < keys.length, j = keys[i]; i++) {tmp[j] = (!tmp[j] ? (pop == '') ? [] : {} : tmp[j]), tmp = tmp[j];}if (pop == '') tmp = (!Array.isArray(tmp) ? [] : tmp), tmp.push(n.value);else tmp[pop] = n.value;} else _[keys.pop()] = n.value;});return _;}console.log($('form').getForm2obj());$('form input').change(function() {console.clear();console.log($('form').getForm2obj());});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script><form><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">male<input type="radio" name="gender" value="female"> female<input name="name2[key1]" value="value1"><input name="one[another][another_one]" value="value4"><input name="name3[1][name]" value="value4"><input name="name3[2][name]" value="value4"><input name="[]" value="value5"></form>

所以我用了公认的答案,发现了一个重大缺陷。
它不支持输入数组,例如:

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

单行(除了jQuery之外没有依赖项),对传递给map方法的函数使用固定对象绑定。

$('form').serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]

它能做什么?

"id=2&value=1&comment=ok" => Object { id: "2", value: "1", comment: "ok" }

适用于渐进式Web应用程序(可以轻松支持常规表单提交操作以及ajax请求)

另一个答案

document.addEventListener("DOMContentLoaded", function() {setInterval(function() {var form = document.getElementById('form') || document.querySelector('form[name="userprofile"]');var json = Array.from(new FormData(form)).map(function(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>Name <input type="text" name="firstname" value="John"/></p><p>Family name <input name="lastname" value="Smith"/></p><p>Work <input name="employment[name]" value="inc, Inc."/></p><p>Works since <input name="employment[since]" value="2017" /></p><p>Photo <input type="file" /></p><p>Send <input type="submit" /></p></form>
JSON: <textarea id="asJSON"></textarea>

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

更现代的方法是以这种方式使用serializeArray()

$('#formid').serializeArray().reduce((a, x) => ({ ...a, [x.name]: x.value }), {});

这将有助于许多“正常”情况。

对于具有重复name属性的多个标签的非常常见的实例,这是不够的。

由于具有重复name属性的输入通常位于某些“包装器”(divultr,…)中,如下例所示:

  <div class="wrapperClass"><input type="text" name="one"><input type="text" name="two"></div><div class="wrapperClass"><input type="text" name="one"><input type="text" name="two"></div>

可以使用map运算符来迭代它们:

$(".wrapperClass").map(function () {return $(this).find('*').serializeArray().reduce((a, x) => ({ ...a, [x.name]: x.value }), {});}).get();

结果将是一个格式为以下的对象数组:

  [{one: valueOfOne,two: valueOfTwo}, {one: valueOfOne,two: valueOfTwo}]

.get()运算符与map结合使用以获取基本数组,而不是jQuery对象,后者提供更清晰的结果。jQuery文档

const formData = new FormData(form);
let formDataJSON = {};
for (const [key, value] of formData.entries()) {
formDataJSON[key] = value;}

Javascript/jQuery one-liner-ish-也适用于旧版本(ES6之前):

$('form').serializeArray().reduce((f,c) => {f[c['name']]=(f[c['name']])?[].concat(f[c['name']],c['value']):c['value']; return f}, {} );

这是一个使用减少的单行代码。Reduce是一个函数函数,它接受传递函数的返回值,并在下一次迭代中将其与列表中的第n个值一起传递回传递的函数。

$('#formid').serializeArray().reduce((o,p) => ({...o, [p.name]: p.value}))

我们必须使用一些技巧才能使其发挥作用:

  • ...o(扩展语法)插入o中的所有key: value
  • 包装我们在()中返回的对象,以将其与表示函数的{}区分开来
  • 将钥匙(p.name)包裹在[]

在一个衬里中利用ES6的优点:

$("form").serializeArray().reduce((o, {name: n, value: v}) => Object.assign(o, { [n]: v }), {});

[更新2020]

使用vanilla js中利用从工单的简单oneliner(一如既往,检查浏览器支持):

Object.fromEntries(new FormData(form))

这段代码为我工作:

  var data = $('#myForm input, #myForm select, #myForm textarea').toArray().reduce(function (m, e) {m[e.name] = $(e).val();return m;}, {});

此代码转换并保存输入类型,而不是将所有输入转换为字符串:

jQuery.fn.serializeForm = function () {var form = this.get(0);var i = [];var ret = {};for (i = form.elements.length - 1; i >= 0; i = i - 1) {if (form.elements[i].name === "") {continue;}var name = form.elements[i].name;switch (form.elements[i].nodeName) {case 'INPUT':switch (form.elements[i].type) {case 'text':case 'tel':case 'email':case 'hidden':case 'password':ret[name] = encodeURIComponent(form.elements[i].value);break;case 'checkbox':case 'radio':ret[name] = form.elements[i].checked;break;case 'number':ret[name] = parseFloat(form.elements[i].value);break;}break;case 'SELECT':case 'TEXTAREA':ret[name] = encodeURIComponent(form.elements[i].value);break;}}return ret;};

例如,这是输出:

Day: 13Key: ""Month: 5OnlyPayed: trueSearchMode: "0"Year: 2021

而不是

Day: "13"Key: ""Month: "5"OnlyPayed: "true"SearchMode: "0"Year: "2021"
function serializedArray2Object(array){let obj = {};array.forEach(function(item){if(obj[item['name']] === undefined){obj[item['name']] = item['value'];}else if(Array.isArray(obj[item['name']])){obj[item['name']] = [...obj[item['name']],item['value']]}else{obj[item['name']] = [obj[item['name']],item['value']];}});return obj;}

使用

serializedArray2Object($('#form').serializeArray())

我刚刚从jQuery中发现了这个函数,并编写了一个对象转换器,以便数组成为一个对象。

这将处理多个选择或甚至具有相同名称的元素:

$.fn.formToJSON = function(){pairStr=this.serialize();let rObj={};pairStr.split(`&`).forEach((vp)=> {prop=vp.split(`=`)[0];val=vp.split(`=`)[1];if(rObj.hasOwnProperty(prop)) {if (Array.isArray(rObj[prop])) {rObj[prop].push(val);} else {rObj[prop]=[rObj[prop]];rObj[prop].push(val);}} else {rObj[prop]=val;}});return JSON.stringify(rObj);}

这使用foreach方法遍历序列化数组返回的名称和值对,然后使用名称作为键返回一个对象。

  let formData = $(this).serializeArray();let formObject = {}formData.forEach(x=>formObject.hasOwnProperty(x.name)?formObject[x.name]=[formObject[x.name],x.value].flat():formObject[x.name]=x.value);

这个线程似乎已经成为表单序列化的集体常见问题解答:)

我对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);

序列化深度嵌套表单没有jQuery

在花了几天时间寻找这个没有依赖关系的问题的解决方案之后,我决定使用FormData API制作一个非jQuery表单数据序列化程序。

序列化器中的逻辑主要基于jQuery插件中的去参数函数,称为jQuery BBQ,但是,在此项目中已删除所有依赖项。

这个项目可以在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;

这和你想要的完全一样

  • 只执行以下代码一次
$.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"}

对于语义-用户界面/fomantic-用户界面,有一个内置行为get values

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

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

获取值(标识符)返回与标识符数组匹配的元素值的对象。如果没有传递IDS,将返回所有字段