2

I'm struggling to dynamically convert a set of inputs into a multi-dimensional object for passing in an ajax call.

Assume I have a Person, with multiple Addresses. My fields currently look like this:

<input name='Person[name]' value='Bradley'/>
<input name='Person[addresses][home]' value='123 Anywhere Drive.'/>
<input name='Person[addresses][work]' value='456 anywhere Road.'/>

How would one convert my fields into ab object that looks like this:

Person :
{
    name: 'Bradley',
    addresses:
    {
        home: '123 Anywhere Drive.',
        work: '456 anywhere Road.'
    }
}

I need to do this dynamically (function needs to work regardless of the inputs provided) and work at N-depth.

(Note: jQuery available).

3
  • This is impossible, unless you want to use a modified (by you) version of serializeObject... Commented Aug 9, 2013 at 20:41
  • 2
    Nothing is impossible. Only impractical. Commented Aug 9, 2013 at 20:42
  • You would need to iterate over the fields, parse the value of the name attribute, then generate multi-dimensional object from it. Since this is not built into jQuery, you'll have to do this yourself. Commented Aug 9, 2013 at 20:44

1 Answer 1

2

http://jsfiddle.net/w4Wqh/1/

Honestly I think there's a way to do this in a regex.. but I couldn't figure it out. So, it's a bit of ugly string manipulation. Either way, this should get you on the right track I think:

function serialize () {
    var serialized = {};
    $("[name]").each(function () {
        var name = $(this).attr('name');
        var value = $(this).val();

        var nameBits = name.split('[');
        var previousRef = serialized;
        for(var i = 0, l = nameBits.length; i < l;  i++) {
            var nameBit = nameBits[i].replace(']', '');
            if(!previousRef[nameBit]) {
                previousRef[nameBit] = {};
            }
            if(i != nameBits.length - 1) {
                previousRef = previousRef[nameBit];
            } else if(i == nameBits.length - 1) {
                previousRef[nameBit] = value;
            }
        }
    });
    return serialized;
}

console.log(serialize());

Quick explanation. This just grabs anything with a 'name' attribute, and then iterates over them. For each iteration, it grabs the name and splits it on '['. This gets you basically how far into the object you need to put things. So, for Person[addresses][work], you would get Person, addresses], work].

Then, there's the tricky part. Since objects are always passed around by reference, we can see if the serialized variable has 'Person' in it. If not, it adds it, and sets the value to an empty object.. which is generic enough to be used for storing more things, or replaced if necessary. If there are no more levels that we need to go through, it just takes the value of the element and assigns it to the reference it has. Otherwise, the code grabs a reference to whatever it just made, and loops again, performing the same operation. So, for Person[addresses][work]..

  1. Does serialized.Person exist? No. Setting serialized.Person to {}. This is not the end of the loop, store reference to serialized.Person as previousRef.
  2. Does previousRef.addresses exist? (serialized.Person.addresses) No. Setting previousRef.addresses to {}. This is not the end of the loop, store reference to previousRef.addresses as previousRef.
  3. Does previousRef.work exist? (serialized.Person.addresses.work) No. Setting previousRef.work to {}. Wait. This is the end of the loop. Setting previousRef.work to the value in the element.
Sign up to request clarification or add additional context in comments.

1 Comment

Heh, great. Updated with some explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.