How can I convert query string or JSON object map to single JSON object with jQuery?
You can try this
String.prototype.QueryStringToJSON = function () {href = this;qStr = href.replace(/(.*?\?)/, '');qArr = qStr.split('&');stack = {};for (var i in qArr) { var a = qArr[i].split('='); var name = a[0], value = isNaN(a[1]) ? a[1] : parseFloat(a[1]); if (name.match(/(.*?)\[(.*?)]/)) { name = RegExp.$1; name2 = RegExp.$2; //alert(RegExp.$2) if (name2) { if (!(name in stack)) { stack[name] = {}; } stack[name][name2] = value; } else { if (!(name in stack)) { stack[name] = []; } stack[name].push(value); } } else { stack[name] = value; }}return stack;}
Query String
href="j.html?name=nayan&age=29&salary=20000&interest[]=php&interest[]=jquery&interest[1]=python&interest[2]=Csharp&fan[friend]=rangan&fan[family]=sujan&sports[1]=cricket&sports[2]=football";
usage
alert(href.QueryStringToJSON().toSource())
output
({name:"nayan", age:29, salary:20000, interest:["php", "python", "Csharp"], fan:{friend:"rangan", family:"sujan"}, sports:{1:"cricket", 2:"football"}})
kgiannakakis's suggestion to traverse the map was a good starting point, though I don't feel that it qualifies as an answer to my original question. After a couple of hours of head banging, I settled for this, which allows you to serialize elements based on a custom attribute (I didn't want to settle for having to use the 'name' attribute on my form elements, which jQuery requires). I have also started using the JSON library from json.org in order to stringify the object I create. The serializeToJSON function of my plugin is what I was looking for as an answer to my question, the rest is just exta.
Note: This is for a client, so the 'CustomXXX' names and attributes were substituted in for what they actually are
jQuery.fn.extend({ serializeCustomPropertyArray: function() { return this.map(function() { return this.elements ? jQuery.makeArray(this.elements) : this; }).filter(function() { return jQuery(this).attr('CustomAttribute') && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password|search/i.test(this.type)); }).map(function(i, elem) { var val = jQuery(this).val(); return val == null ? null : jQuery.isArray(val) ? jQuery.map(val, function(val, i) { return { name: jQuery(elem).attr('CustomAttribute'), value: val }; }) : { name: jQuery(elem).attr('CustomAttribute'), value: val }; }).get(); }, serializeToJSON: function() { var objectMap = this.serializeCustomPropertyArray(); var objectJson = new Object; jQuery.each(objectMap, function() { objectJson[this.name] = (this.value !== null) ? this.value : 'null'; }); return JSON.stringify(objectJson); }});
This can be called like:
$('#fields').find(':input[CustomGroup="Months"]').serializeToJSON();
Assuming your document looks something like:
<div id="fields"> <input type="checkbox" CustomGroup="Months" CustomAttribute="January" />January<br /> <input type="checkbox" CustomGroup="Months" CustomAttribute="February" />February<br /> ...</div>
The JSON that's built looks like:
{ January: 'on', February: 'on', ... }
You can traverse an object map using the $.each utility function.
$(function() { map = [{ January: 'on' },{ March: 'on' },{ September: 'on' }]; $.each(map, function() { $.each(this, function(key, val) {alert(key + " = " + val);});; });});
The first each gets you all array objects. With the second one you can get the key and value of your object.