如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').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请求)
其他回答
更现代的方法是将reduce与serializeArray()一起使用,方法如下:
$('#formid').serializeArray()
.reduce((a, x) => ({ ...a, [x.name]: x.value }), {});
这将有助于许多“正常”情况。
对于具有重复名称属性的多个标记的非常常见的实例,这是不够的。
由于具有重复名称属性的输入通常位于某些“包装器”(div,ul,tr,…)内,如本示例所示:
<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>
可以使用reduce和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文档
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;
};
我喜欢塞缪尔的版本,但我相信它有一个小错误。通常JSON发送为
{“coreSKU”:“PCGUYJS”,“name_de”:“whatever”,。。。
不作为
〔{“coreSKU”:“PCGUYJS”},{“name_de”:“whatever”},。。。
因此,功能IMO应为:
App.toJson = function( selector ) {
var o = {};
$.map( $( selector ), function( n,i )
{
o[n.name] = $(n).val();
});
return o;
}
并将其包装在数据数组中(正如通常预期的那样),最后将其作为跨页发送App.stringify({data:App.toJson(“#cropform:input”)})
对于精简版本,请参见问题3593046,对于所有可能的版本,请参阅json2.js。这应该涵盖了所有内容:)
在不检查每个元素的情况下,确实无法做到这一点。您真正想知道的是“是否有其他人已经编写了一个将表单转换为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;
}
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
}, "");
}