2010-09-09 14 views
19

Szukałem godzin na to i nie znalazłem odpowiedzi. Proszę przeczytać całe pytanie przed płonąć! :)Serialize złożony formularz do obiektu JSON przy użyciu jQuery

Mam formularz podobny do tego:

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

i muszą być w stanie szeregować je w ten sposób:

{ 
name: 'name value', 

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

Próbowałem większość odpowiedzi na SO tym jQuery json biblioteki i większość z nich coś powrócić tak:

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

to jest coś Nie mogę użyć! : P

Dziękuję wszystkim z góry.

Odpowiedz

18

Spróbuj tego kodu, który napisałem dla ciebie ... Działa dobrze dla mnie, po prostu używając twojego wyniku danych. Możesz na nim popracować i stworzyć prostą wtyczkę jQuery ...

Próbka wymaga JSON.stringify do pełnej pracy.

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

Dziękuję bardzo Juliano! To jest idealne rozwiązanie! : D –

+0

Działa jak magia. Miał niewielką modyfikację, aby obsłużyć sytuację, w której Twoja lista ma postać: var d = { 'name': 'name value', 'telefon [0] .type': 'cell', 'telefon [0] .numer ":" 000 ", " phone [1] .type ":" home ", " phone [1] .number ":" 111 ", }; Wynik zawiera (.) Wejścia z wewnętrznej listy Klawisz, więc dodałem Po pierwszej pętli for w processExpression (). –

+0

_key_ jest dwukrotnie deklarowany w funkcji. – robsch

1

W tej strukturze nie sądzę, że biblioteka JSON może wykonać całą pracę. Myślę więc, że łatwiej jest napisać własną pętlę konwersji.

Oto kod do serializacji: http://jsfiddle.net/7MAUv/1/

Logika jest dość prosta, sekret jest eval uruchomić Strings jak dynamicznych poleceń. Starałem się, aby było to tak proste, jak to możliwe, prawie wszystkie linie są komentowane.

BTW, może swobodnie zadawać pytania.

+0

Twój kod działa idealnie Erick. Dziękuję bardzo za opublikowanie tego. Postaram się sprawdzić, czy można to zrobić bez części ewaluacyjnej, ale na razie powinna być świetna. –

2

To działało bardzo dobrze dla mnie. To nie musi mieć biblioteki 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; 
    }; 

Aby przetworzyć dane formularza, użyłem tego kodu.

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

Jeśli masz jakiekolwiek wątpliwości, możesz dodać komentarz.

+0

Jak wygląda twoja forma, aby to zadziałało? – trebor

0

Nie jest dokładnie to, co prosiłeś, ale jeśli używasz biblioteki jQuery i wymagają skomplikowanego formularza odcinkach na celu wysłania go w AJAX, można użyć czegoś jak ten

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

można wykorzystać w $ .post i $ .get również

nJoy!

Powiązane problemy