Serialize form data to json with jquery

I worked on new plevsy all day, and at some point i got in need of some function to serialize forms into deep json objects so that i can push whatever the form has, directly to couchdb. None of solutions i got from some googling satisfied me so i took a shot at my first jquery plugin. Well, it wasn’t a jquery plugin at the first place, but i thought it would be much re-usable.

(function( $ ){
  $.fn.toDeepJson = function() {
    function parse(val){
      if (val == ""){ return null; }
      if (val == "true"){ return true; }
      if (val == "false"){ return false; }
      return val;      
    }
    function toNestedObject(obj, arr){
      var key = arr.shift();
      if (arr.length > 0) {
        obj[key] = toNestedObject(obj[key] || {}, arr);
        return obj;
      }
      return key;
    }
    if (this.length == 1){
      return $.makeArray(this[0].elements)
      .filter(function(e){
          return e.name != "" && (e.type == 'radio' ? e.checked : true);
      })
      .map(function(e){
          var names = e.name.split('.');
          if (e.type == 'checkbox') {
            e.value = e.checked;
          }
          names.push(parse(e.value));
          return names;
      })
      .reduce(toNestedObject, {});
    } else {
      throw({error:"Can work on a single form only"})
    }
  };

  $.flatten = function (obj){
    var ret = {}
    for (var key in obj){
      if (typeof obj[key] == 'object'){
        var fobj = $.flatten(obj[key]);
        for (var extkey in fobj){
          ret[key+"."+extkey] = fobj[extkey];
        }
      } else {
        ret[key] = String(obj[key]);
      }
    }
    return ret;
  }
  
})( jQuery );

You’ll need firefox >= 3.x or some high-end browser which supports javascript Array functions map and reduce at the same time. Older browsers may use a work around as shown here and here.

Anyway, it is supposed to work like that:

<form id="regform">
  <input type="hidden" name="prodtype" value="reg"/>
  <input type="text" name="name"/>
  <input type="text" name="prices.Early"/>
  <input type="text" name="prices.Late"/>
  <input type="text" name="prices.On-site"/>
</form>
var doc = $('#regform').toDeepJson(); 
// doc should be
{
  prodtype: "reg",
  name: "nameValue",
  prices: {
    Early: "earlyValue",
    Late: "lateValue",
    On-site: "onsiteValue",
  }
}

Reverse function is also available, so it is possible to populate the same form, from the json:

var fdoc = $.flatten(doc);
for (var name in fdoc){
  $('[name='+name+']','#regform').val(fdoc[name]);
}

I didn’t test for input types like radio and checkbox right now, so i don’t know how it’s going to work with them. I’m sure i’ll find out soon enough and come back here for a patch.

UPDATE : Fixed to work with radio and checkbox. Checkboxes will need to define value=”true”.

UPDATE : I’ve put the code here along with the crud widget.

Notes

  1. agaoglu posted this