2010-09-09 76 views
19

我一直在为此寻找小时,并且没有找到答案。 在燃烧之前请仔细阅读整个问题! :)使用jQuery将复杂形式序列化为JSON对象

我有一个类似的形式:

<form id="sample"> 
<input name="name" type="text" value="name value" /> 

<input name="phone[0][type]" type="text" value="cell" /> 
<input name="phone[0][number]" type="text" value="000" /> 

<input name="phone[1][type]" type="text" value="home" /> 
<input name="phone[1][number]" type="text" value="111" /> 
</form> 

而且需要能够将其序列化到这一点:

{ 
name: 'name value', 

phone: [ 
    { 
    type: 'cell', 
    number: '000' 
    }, 
    { 
    type: 'home', 
    number: '111' 
    } 
] 
} 

我曾尝试在SO包括jQuery的JSON最答案库和大多数人返回这样的事情:

{ 
'name': 'name value', 
'phone[0][type]': 'cell', 
'phone[0][number]': '000', 
'phone[1][type]': 'home', 
'phone[1][number]': '111', 
} 

这是东西我不能使用! :P

谢谢大家提前。

回答

18

试试这段代码我为你写的...对我来说工作得很好,只是使用你的数据结果。你可以使用它来制作一个简单的jQuery插件...

该示例需要JSON.stringify才能完全工作。

var d = { 
    'name': 'name value', 
    'phone[0][type]': 'cell', 
    'phone[0][number]': '000', 
    'phone[1][type]': 'home', 
    'phone[1][number]': '111', 
}; 

$(document).ready(function(){ 

    arrangeJson(d); 
    alert(JSON.stringify(d)); 
}); 

function arrangeJson(data){ 
    var initMatch = /^([a-z0-9]+?)\[/i; 
    var first = /^\[[a-z0-9]+?\]/i; 
    var isNumber = /^[0-9]$/; 
    var bracers = /[\[\]]/g; 
    var splitter = /\]\[|\[|\]/g; 

    for(var key in data) { 
     if(initMatch.test(key)){ 
      data[key.replace(initMatch,'[$1][')] = data[key]; 
     } 
     else{ 
      data[key.replace(/^(.+)$/,'[$1]')] = data[key]; 
     } 
     delete data[key]; 
    } 


    for (var key in data) { 
     processExpression(data, key, data[key]); 
     delete data[key]; 
    } 

    function processExpression(dataNode, key, value){ 
     var e = key.split(splitter); 
     if(e){ 
      var e2 =[]; 
      for (var i = 0; i < e.length; i++) { 
        if(e[i]!==''){e2.push(e[i]);} 
      } 
      e = e2; 
      if(e.length > 1){ 
       var x = e[0]; 
       var target = dataNode[x]; 
       if(!target){ 
        if(isNumber.test(e[1])){ 
         dataNode[x] = []; 
        } 
        else{ 
         dataNode[x] ={} 
        } 
       } 
       processExpression(dataNode[x], key.replace(first,''), value); 
      } 
      else if(e.length == 1){ 
       dataNode[e[0]] = value; 
      } 
      else{ 
       alert('This should not happen...'); 
      } 
     } 
    } 
} 
+1

非常感谢Juliano! 这是完美的解决方案! :D – 2010-09-09 15:29:09

+0

工程像魔术。对其进行一些修改,以处理您的列表形式为 var d = {name':'name value', 'phone [0] .type':'cell', 'phone [0] .number':'000', 'phone [1] .type':'home', 'phone [1] .number':'111', }; 结果在内部列表Key中有(。)in from,所以我在processExpression的第一个for循环后面添加了 )功能。 – 2016-02-05 16:13:02

+0

_key_在函数中被声明了两次。 – robsch 2016-05-14 14:16:42

1

有了这个结构,我不认为任何JSON库可以完成所有的工作。 所以,我认为编写自己的转换循环更容易。

下面是代码到您的序列:http://jsfiddle.net/7MAUv/1/

的逻辑很简单,秘诀是eval跑般的动感命令字符串。 我试图让它尽可能地简单,几乎所有的行都被评论了。

顺便说一句,随时提出问题。

+0

你的代码完美工作Erick。 非常感谢您发布它。 我会尝试看看是否可以完成没有eval部分,但现在应该是真棒。 – 2010-09-09 14:04:56

2

这个工作对我非常好。这并不需要form2js库。

$.fn.serializeObject = function serializeObject() { 
     var o = {}; 
     var a = this.serializeArray(); 
     $.each(a, function() { 
      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 || ''; 
      } 
     }); 
     return o; 
    }; 

要序列化表单数据,我使用了这段代码。

JSON.stringify($(this).serializeObject());//'this' points to the form 

如果您有任何疑问,请随时添加评论。

+0

为了实现这个目标,你的表单是什么样的? – trebor 2016-01-12 14:27:00

0

它不是你问什么了,但如果你正在使用jQuery库,需要你的连载在AJAX发送它的目的复杂的形式,你可以使用某事像这样

ajaxRunning = $.ajax(
    "?"+$('#yourForm').serialize(), 
    { 
     data: { 
      anotherData: 'worksFine', 
      etc: 'still works' 
     }, 
     success: function(result) { 
      doSth(); 
     }, 
     dataType: "json" 
}); 

可以使用in $ .post and $ .get以及

nJoy!