2010-12-03 13 views
5

basándose en la función $.fn.serializeObject() de this question, me gustaría ser capaz de soportar "notación de puntos" en mis nombres de formulario, así:caso especial de la serialización de forma a un objeto 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> 

teniendo en cuenta que $('form').serializeArray() produce los siguientes:

[{"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"}] 

cómo podría i lograr el resultado deseado a continuación:

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

cualquier ayuda sería apreciada.

EDIT: para ser específico, el código deseado se agregaría a la extensión serializeObject para que, además de la forma en que funciona ahora, también sería compatible con la convención anterior. aquí está el método existente por conveniencia.

$.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: alimentándose de la respuesta proporcionada, aquí está mi aplicación actual:

$.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; 
}; 

se puede ver en acción here

+0

Niza, 2 cosas. No hay necesidad de usar $ .each aquí solo está por encima. Un for-loop regular lo hará. 2. No declare 'var' en un bucle (para, mientras). En Javascript, volver a asignar una var es mucho más rápido y declarar una nueva 'var' cada vez. Así que establece 'var' fuera de los bucles. – fredrik

+0

@Omer, ¿qué comprueba exactamente su/^ ([^ \ [\]] +) \ [(\ d +) \] $/expresión? – R4nc1d

Respuesta

4

Esta solución es un poco estática. Pero debería hacer el truco:

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 gracias. parece funcionar después de cambiar $ .fn.serializeObject() a $(). serializeArray(). probará con más detalle y seguimiento. –

+0

pude mejorar tu respuesta ... compruébalo en la publicación. gracias de nuevo. –

Cuestiones relacionadas