24

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.

3

6 Answers 6

19

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...');
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Works like magic. Had a little modification to it to handle a situation where your List is in the form var d = { 'name': 'name value', 'phone[0].type': 'cell', 'phone[0].number': '000', 'phone[1].type': 'home', 'phone[1].number': '111', }; The result has (.) in from of the inner list Key, So I added <e2[0] = e2[0].replace('.','');> after the first for loop in the processExpression() function.
key is twice declared in the function.
6

There is also the following library

http://code.google.com/p/form2js/

Comments

2

This worked very well for me. This doesn't need to have the form2js library.

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

To serialise the form data I used this code then.

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

If you have any doubts please feel free to add comment.

1 Comment

What does your form look like in order for this to work?
1

With this structure, I don't think any JSON library can do all the work. So, I think that is more easy to write our own conversion loop.

Here is the code to your serialization: http://jsfiddle.net/7MAUv/1/

The logic is pretty simple, the secret is the eval to run Strings like dynamic commands. I tried to make it as easier as possible, almost all lines are commented.

BTW, feels free to make questions.

1 Comment

Your code works perfectly Erick. Thank you very much for posting it. I will try and see if can be done without the eval part but should be awesome for now.
0

Its not exactly what you asked for, but if you are using jQuery library and need your complex form serialized for a purpose of sending it in ajax, you can use sth like this

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

you can use in $.post and $.get as well

nJoy!

Comments

0

Another library that solves this issue is jquery.serializeJSON by Mario Izquierdo. It works and extends jQuery.

Comments

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.