标签的用武之地!我们将使用
标记来表示表单/xml表示中的所有容器元素,从而得到如下结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
< 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对象,其外观如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
{ 'places' : {
'place' : [
{
'name' : 'Home' ,
'type' : 'dwelling' ,
'activity' : [
'sleep' ,
'eat' ,
'watch TV'
]
} ,
{ ...} ,
{ ...}
]
} }
为了做到这一点,我在这里开发了这个jquery插件,有人帮助优化了这个代码审查线程,看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$.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(甚至是收音机和复选框),您只需调用
1
$.post ( 'script.php' , ( 'form' ) .toJSO ( ) , ...) ;
我知道有很多方法可以将表单转换为JSON对象,而且在大多数情况下,.serialize() 和.serializeArray() 的效果都很好,而且大多数情况下都是有意使用的,但我认为将表单编写为具有有意义名称的XML结构并将其转换为格式良好的JSON对象的整个想法是值得尝试的,而且您可以添加如果需要检索动态生成的表单数据,无需担心的同名输入标记非常有用。
我希望这能帮助别人!
我发现所选解决方案有问题。
当使用具有基于数组的名称的表单时,jquery serialiarray()函数实际上会终止。
我有一个PHP框架,它使用基于数组的字段名,允许同一表单在多个视图中多次放到同一页上。这可以方便地将添加、编辑和删除放在同一页上,而不会与表单模型冲突。
因为我想在不需要去掉这个绝对基本功能的情况下对表单进行血清化,所以我决定编写自己的seralizearray():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
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 ;
}
} ) ;
请注意:这在表单submit()之外也有效,因此如果您的其余代码中发生错误,那么如果您将链接按钮置于"保存更改"上,表单将不会提交。
另外请注意,此函数绝不应仅用于验证表单,以收集发送到服务器端进行验证的数据。使用这种弱代码和大量分配的代码将导致XSS等。
我更喜欢这种方法,因为:您不必迭代两个集合,如果需要,您可以获取除"name"和"value"之外的内容,并且可以在将值存储到对象中之前对其进行清理(例如,如果您有不希望存储的默认值)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
$.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;
}
使用如下:
1
var obj = $.formObject ( $( "#someForm" ) ) ;
仅在Firefox中测试。
我自己将表单编码为多维JavaScript对象,以便在生产中使用。结果是https://github.com/serbanghita/formtoobject.js。
我在一个非常具体的实现中使用了这个变体,非常感谢!
谢谢你让我知道它很有用。我有一些即将推出的功能,这激励了我。
把任何东西变成一个物体(不是单元测试)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
< 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] ) ;
else
arr1[ 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] + '"' ;
}
else
return ':{"' + escape( arguments[ 1 ] ) + '"' ;
} ) + ':"' + value.replace ( /[\"]/gi , function ( )
{
return "\" +arguments[0];
})+'" '+string.repeat(' } ', string.count(name, ' ] '))+"}");
o = array.merge(o, obj);
});
return o;
}
测试输出:
1 2 3 4 5
$( document) .ready ( function ( )
{
console.log ( array.print ( node.objectify ( $( "form" ) , { } ) ) ) ;
console.log ( array.print ( node.objectify ( $( "form" ) , { selector: "select" } ) ) ) ;
} ) ;
在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
< 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>
收益率:
1 2
{ input: { a: text, b: select } , otherinput: { c: { a: a, 0 : b, 1 : d } , d: { b: c } } , anotherinput: 1 }
{ input: { b: select } }
我喜欢萨缪尔版本,但我相信它有一个小错误。通常JSON发送为
{"coreSKU":"PCGUYJS","name_de":"whatever",...
不如
< Buff行情>["coresku":"pcguyjs
另一个答案
1 2 3 4 5 6 7 8 9
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 ) ;
} )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
< 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
使用罗达什集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
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"
}
我喜欢这个解决方案,但它不处理key[] 数组格式的表单字段;[ {key: 'items[]', value: 1 }, {key: 'items[]', value: 2 } ] 导致{ items: {"": 2 } } 。
要获得快速、现代的解决方案,请使用jsonify jquery插件。下面的示例是从Github自述文件中逐字提取的。所有的功劳都归功于这个插件的作者Kushal Pandya。
鉴于:
1 2 3 4 5 6 7 8
< 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>
运行:
生产:
如果要使用此JSON对象执行jquery发布:
1 2 3
$( '#mybutton' ) .click ( function ( ) {
$.post ( '/api/user' , JSON.stringify ( $( '#myform' ) .jsonify ( ) ) ) ;
}
如果要将表单转换为javascript对象,那么最简单的解决方案(此时)是使用jquery的each 和serializeArray 函数方法。
1 2 3 4 5 6 7 8 9
$.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网站
可与Bower一起安装:bower install git://github.com/tfmontague/form-object.git
由于XSS攻击和其他许多问题,我不会在活动站点上使用此功能,但下面是一个简单的示例,说明您可以做什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$( "#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 ;
} ) ;
你不能先把XSS转换成JS对象,而不是直接转换成字符串,以此来避开XSS攻击吗?
1 2 3 4 5 6 7 8
const formData = new FormData( form) ;
let formDataJSON = { } ;
for ( const [ key, value] of formData.entries ( ) ) {
formDataJSON[ key] = value;
}
所以我用了公认的答案,发现了一个重大的缺陷。它不支持如下输入数组:
1 2 3
< input type= "checkbox" name= "array[]" value= "1" />
< input type= "checkbox" name= "array[]" value= "2" />
< input type= "checkbox" name= "array[]" value= "3" />
这一微小的变化应该可以解决以下问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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(); 的输出传递给它,否则它将不起作用。
如果使用JSON发送表单,则在发送字符串时必须删除[]。可以使用jQuery函数serializeObject()执行此操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
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 field
var $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 ( ) ;
else
elemValue = 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;
}
更现代的方法是使用reduce和serializeArray() 的方式:
1 2
$( '#formid' ) .serializeArray ( )
.reduce ( ( a, x) => ( { ...a , [ x.name ] : x.value } ) , { } ) ;
它将有助于许多"正常"案例。
对于具有重复name 属性的多个标记的非常常见的情况,这是不够的。
由于具有重复name 属性的输入通常位于某些"包装器"(div 、ul 、tr …)内,如本例中所示:
1 2 3 4 5 6
< input type= "text" name= "one" >
< input type= "text" name= "two" >
< input type= "text" name= "one" >
< input type= "text" name= "two" >
我们可以使用reduce和map 运算符来迭代它们:
1 2 3 4
$( ".wrapperClass" ) .map ( function ( ) {
return $( this ) .find ( '*' ) .serializeArray ( )
.reduce ( ( a, x) => ( { ...a , [ x.name ] : x.value } ) , { } ) ;
} ) .get ( ) ;
结果将是一个对象数组,格式为:
1 2 3 4 5 6 7 8 9
[
{
one: valueOfOne,
two: valueOfTwo
} , {
one: valueOfOne,
two: valueOfTwo
}
]
.get() 运算符与map 结合使用,得到基本数组,而不是jquery对象,结果更清晰。jQuery文档
以下是非jquery方法:
1 2 3 4 5 6
var getFormData = function ( form) {
//Ignore the submit button
var elements = Array .prototype .filter .call ( form.elements , function ( element) {
var type = element.getAttribute ( 'type' ) ;
return ! type || type.toLowerCase ( ) !== 'submit' ;
} ) ;
您可以这样使用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
function ( ) {
var getFormData = function ( form) {
//Ignore the submit button
var 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 it
post( action, data, console.log .bind ( console) ) ;
}
//change formName below
document.formName .onsubmit = submit;
} ) ( ) ;
我编写了一个jquery模块jsform,它可以双向执行,即使对于非常复杂的表单也是如此(还允许集合和其他更复杂的结构)。
它使用字段的名称(加上一些集合的特殊类),并匹配一个JSON对象。它允许自动复制用于收集和数据处理的DOM元素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
< html>
< head>
< script src= "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" >
< script src= "https://raw.github.com/corinis/jsForm/master/src/jquery.jsForm.js" >
$( function ( ) {
// Some JSON data
var jsonData = {
name: "TestName" , // Standard inputs
description: "long Description
Multiline" , // Textarea
links: [ { href: 'http://stackoverflow.com' , description: 'StackOverflow' } , { href: 'http://www.github.com' , description: 'GitHub' } ] , // Lists
active: true , // Checkbox
state: "VISIBLE" // Selects (enums)
} ;
// Initialize the form, prefix is optional and defaults to data
$( "#details" ) .jsForm ( {
data: jsonData
} ) ;
$( "#show" ) .click ( function ( ) {
// Show the JSON data
alert( JSON.stringify ( $( "#details" ) .jsForm ( "get" ) , null , "" ) ) ;
} ) ;
} ) ;
</ head>
< body>
Simpel Form Test
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" />
< button id= "show" > Show Object</ button>
</ body>
</ html>
我不得不无耻地自我推销我的表单库。
变换。它执行以下操作:序列化、反序列化、清除和提交表单。
我之所以这样做,是因为Form2JS/JS2Form没有得到维护,也没有我想要的那样灵活和快速。我们在生产中使用它是因为它与Form2JS/JS2Form兼容。
我最近遇到了同样的问题,所以我开发了一个函数,它允许解析表单的控件以获取控件ID/值并将其转换为JSON。
它足够灵活,可以添加更多控件。只需指定要解释为值的控件类型和属性。
你可以在这里找到完整的脚本。
其优点是它只获取您实际需要的数据,而不拖动整个对象。
disshampage是指如果您有嵌套的选项,那么您需要相应地给ID加前缀,这样您就可以对其特定的组使用重复的选项。
希望这有帮助!
不过,正如commenter@macek所指出的那样,tobias上面的解决方案是正确的,它不处理foo[bar]类型的输入,并将其拆分为子对象。
这是一个仅限PHP的特性,但是我仍然发现能够在JavaScript中生成相同的结构非常有用。
我只是在上面修改了托比亚斯的代码,所以所有的功劳都归他。这可能会变得更干净,但我只是在五分钟内快速完成,并认为它可能有用。
它此时不处理多维数组或数字索引数组。也就是说,它只适用于foo[bar]的名称,而不适用于foo[]。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
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;
} ;
好像你没看过我的全部评论。我设计了一个解决方案来处理foo[bar] 类型的输入和foo[bar][bof][a][b][etc] ;请参阅本文中的答案。另外请注意,foo[bar] 的"解析"不是PHP独有的。Rails在很大程度上依赖于此约定将表单属性传递给对象。
这是对Tobias-Cohen函数的改进,该函数适用于多维数组:
http://jsfiddle.net/bnnwf/2/
但是,这不是一个jquery插件,但是如果您希望这样使用它,只需几秒钟就可以将其变成一个插件:只需替换函数声明包装器:
1 2 3 4
function serializeFormObject( form)
{
...
}
用:
1 2 3 4 5
$.fn .serializeFormObject = function ( )
{
var form = this ;
...
} ;
我想这和麦塞克的解决方案相似,因为它做了同样的事情,但我认为这有点干净和简单。我还将Macek的测试用例输入包含到小提琴中,并添加了一些额外的输入。到目前为止,这对我很有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
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 object
if ( 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 part
var 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 = [ ] ;
else
next = { } ;
}
}
if ( trim( this ) == '' ) {
temp.push ( next) ;
} else
temp[ this ] = next;
temp = next;
} ) ;
}
} ) ;
return o;
}
我的代码来自我的库phery,它有一个串行化例程,可以处理非常复杂的表单(比如在demo https://github.com/pocesar/phery/blob/master/demo.php l1664中),而且它不是一个适合所有人的大小。它实际上检查每个字段的类型。例如,一个无线电设备与一个范围不同,它与keygen不同,它与select multiple不同。我的职能涵盖了这一切,你可以看到网址:https://github.com/pocesar/phery/blob/master/phery.js_l1851。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
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;
}
它是我的图书馆信息系统的一部分,但是它可以移植到你自己的项目中。它在应该有数组的地方创建数组,从select、normalize复选框选项等中获取正确的所选选项。如果要将其转换为json(真正的json字符串),只需执行JSON.stringify($('form').serializeForm()); 。
堆栈溢出不在这里,您不能提升您的库。
好的,但是serializeForm 是我的图书馆的一部分,完全按照操作人员的要求来做。
最后一根绳子是最好的
这个解决方案更好。这里的一些更流行的选项在未选中复选框时不更正句柄复选框。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
getData: function ( element) {
//@todo may need additional logic for radio buttons
var 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;
}
serialize函数以json对象为参数,返回serialize字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
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' ,
'
' : '\
' ,
'\f ' : '\\ f' ,
'
' : '\
' ,
'"' : '\" ' ,
'\' : ' \\\'
}, EMPTY = ' ', OPEN_O = ' { ', CLOSE_O = ' } ', OPEN_A = ' [ ', CLOSE_A = ' ] ', COMMA = ' , ', COMMA_CR =",
", CR ="
", 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) +"
] "
:" {
" + _indent(a.join(COMMA_CR), space) +"
} ";
}
else {
return arr ?" [ " + a.join(COMMA) +" ] " :" { " + a.join(COMMA)
+" } ";
}
}
return serialize({
" " : object
}," ");
}
此函数返回所有转换为正确类型的值;
可能的bool/string/(integer/floats)
您可能需要jquery,但由于serialiarray也是jquery,所以没有什么大不了的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/**
* 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 number
var isNum = /^\d+$/ .test ( value) ;
if ( isNum) value = parseFloat( value) ;
// check if we have a boolean
var isBool = /^(false|true)+$/ .test ( value) ;
if ( isBool) value = ( value!== "false" ) ;
}
json[ obj.name ] = value;
} ) ;
return json;
}
} ) ( jQuery) ;
创建一个映射并循环所有字段,保存它们的值。
1 2 3 4
var params = { } ;
$( "#form" ) .find ( "*[name]" ) .each ( function ( ) {
params[ this .getAttribute ( "name" ) ] = this .value ;
} ) ;
使用此:
1 2 3 4 5 6 7 8
var sf = $( '#mainForm' ) .serialize ( ) ; // URL encoded string
sf = sf.replace ( /"/g , '"' ) ; // Be sure all"s are escaped
sf = '{"' + 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) ;
它就像一个魅力,即使在非常复杂的形式。
这对eval 用户输入是有风险的,任何事情都可能发生。我强烈建议不要这样做。