2010-12-03 7 views
5

bâtiment sur la fonction $.fn.serializeObject() de this question, je voudrais être en mesure de soutenir « la notation par points » dans mes noms de forme, comme ceci:cas particulier de la forme sérialisation à un objet javascript

<form> 
    <input name="Property.Items[0].Text" value="item 1" /> 
    <input name="Property.Items[0].Value" value="1" /> 
    <input name="Property.Items[1].Text" value="item 2" /> 
    <input name="Property.Items[1].Value" value="2" /> 
</form> 

étant donné que $('form').serializeArray() produit les éléments suivants:

[{"name":"Property.Items[0].Text","value":"item 1"}, 
{"name":"Property.Items[0].Value","value":"1"}, 
{"name":"Property.Items[1].Text","value":"item 2"}, 
{"name":"Property.Items[1].Value","value":"2"}] 

comment pourrais-je obtenir le résultat désiré ci-dessous:

{Property: {Items: [{Text: 'item 1', Value: '1'}, 
        {Text: 'item 2', Value: '2'}]} } 

toute aide serait appréciée.

EDIT: pour être spécifique, le code souhaité serait ajouté à l'extension serializeObject afin qu'en plus de la façon dont cela fonctionne maintenant, il prendrait également en charge la convention ci-dessus. voici la méthode existante pour plus de commodité.

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

EDIT 2: se nourrissant de la réponse fournie, voici mon implémentation actuelle:

$.fn.serializeObject = function() { 
    var o = {}; 
    var a = this.serializeArray(); 
    var regArray = /^([^\[\]]+)\[(\d+)\]$/; 

    $.each(a, function(i) { 
     var name = this.name; 
     var value = this.value; 

     // let's also allow for "dot notation" in the input names 
     var props = name.split('.'); 
     var position = o; 
     while (props.length) { 
      var key = props.shift(); 
      var matches; 
      if (matches = regArray.exec(key)) { 
       var p = matches[1]; 
       var n = matches[2]; 
       if (!position[p]) position[p] = []; 
       if (!position[p][n]) position[p][n] = {}; 
       position = position[p][n]; 
      } else { 
       if (!props.length) { 
        if (!position[key]) position[key] = value || ''; 
        else if (position[key]) { 
         if (!position[key].push) position[key] = [position[key]]; 
         position[key].push(value || ''); 
        } 
       } else { 
        if (!position[key]) position[key] = {}; 
        position = position[key]; 
       } 
      } 
     } 
    }); 
    return o; 
}; 

vous pouvez le voir en action here

+0

Nice, 2 choses. Il n'y a pas besoin d'utiliser $ .each ici c'est juste les frais généraux. Un for-loop régulier le fera. 2. Ne déclarez pas 'var' dans une boucle (pour, while). En Javascript, réattribuer une var est beaucoup plus rapide que de déclarer une nouvelle variable 'var' à chaque fois. Donc, mettez-vous 'var' en dehors des boucles. – fredrik

+0

@Omer, qu'est-ce que votre expression/^ ([^ \ [\]] +) \ [(\ d +) \] $/expression vérifie exactement? – R4nc1d

Répondre

4

Cette solution est un peu statique. Mais il devrait faire l'affaire:

var serialized = $.fn.serializeObject(), 
      properties = {}, 
      property = [], 
      position = {}, 
      key = '', 
      n = 0, 
      matchName = '', 
      i = 0; 

     for (i = 0; i < serialized.length; i += 1) { 
      property = serialized[i].name.split('.'); 
      position = properties; 
      while (property.length) { 
       key = property.shift(); 
       if (key.match(/\[\d+\]/) && key.match(/\[\d+\]/).join().match(/\d+/g)) { 
        matchName = key.match(/\w+/)[0] 
        n = parseInt(key.match(/\[\d+\]/).join().match(/\d+/g), 10); 
        if (!position[matchName]) { 
         position[matchName] = []; 
        } 

        if (!position[matchName][n]) { 
         position[matchName][n] = {} 
        } 

        position = position[matchName][n] 
       } else { 
        if (!property.length) { 
         position[key] = serialized[i].value 
        } else { 
         if (!position[key]) { 
          position[key] = {}; 
         } 
         position = position[key] 
        } 
       } 

      } 
     } 

     console.log(properties); 
+0

+1 merci. il semble fonctionner après avoir changé $ .fn.serializeObject() en $(). serializeArray(). va tester plus en détail et de suivi. –

+0

J'ai été en mesure d'améliorer votre réponse ... vérifier dans le post. Merci encore. –