George Antoniadis George Antoniadis - 6 months ago 13
Javascript Question

Serialize complex form to JSON object using jQuery

I've been searching for hours for this and haven't found an answer.
Please read through the whole question before flaming! :)

I have a form similar to this:

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


And need to be able to serialize it to this:

{
name: 'name value',

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


I have tried most answers on SO including jquery-json libraries and most of them return something like this:

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


This is something I cannot use! :P

Thanks everyone in advance.

Answer

Try this code I wrote for you... Works fine for me, just using your data result. You can work on it and make a simple jQuery plugin...

The sample need JSON.stringify to work fully.

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...');
            }
        }
    }
}