Reputation: 77778
If I have the following form:
<form>
<input name="foo" value="bar">
<input name="hello" value="world">
<input name="animals[]" value="panda">
<input name="animals[]" value="koala">
<input name="car[make]" value="Honda">
<input name="car[origin]" value="Japan">
</form>
I do not want to use $("form").serialize()
:
foo=bar&hello=world&animals%5B%5D=panda&animals%5B%5D=koalacar&%5Bmake%5D=Honda&car%5Borigin%5D=Japan
Instead, I want this:
{"foo":"bar", "hello":"world", "animals":["panda", "koala"], "car":{"make":"Honda", "origin":"Japan"}}
To my understanding, jQuery used to do this, but they switched the serialize
method to return the GET-style query string. Is there an easy way to get my desired result?
I've updated my original question to include car[make]
and car[origin]
examples. It should be assumed that foo[bar][baz]
or foo[bar][baz][bof]
input could appear on the form as well.
Additionally, numerically indexed keys that are specified such as foo[0]=a
, foo[1]=b
, foo[4]=c
should be preserved, e.g.,
{ ... "foo":["a", "b", undefined, undefined, "c"] ... }
Upvotes: 6
Views: 8483
Reputation: 1067
In my case, I had to take a form I had previously serialized using jQuery and convert it into an object, replacing all encoding for special characters, etc. with their literal value. Using Dilip's example here, this is what I used.
Form1 = $('#MyForm').serialize(); // Name=Mr.+John+Mark+Jr.&Email=john%40example.com
Form1 = Form1.replace(/\+/g, '%20'); // Name=Mr.%20John%20Mark%20Jr.&Email=john%40example.com
var Decoded = decodeURIComponent(Form1); // Name=Mr. John Mark Jr.&[email protected]
var Values = queryParamsToJson(Decoded); // { Name : "Mr. John Mark Jr.", Email : "[email protected]" }
function queryParamsToJson(theURL)
{
href = theURL;
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;
}
Now I can access any value as "Values.variable"
Upvotes: 0
Reputation: 7074
This is a very good answer to convert the querystring to JSON. I got from the following SO link
knovel.util = {
queryParamsToJson : function (theURL) {
href = theURL;
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;
}
}
Hope this helps some one..
Upvotes: 1
Reputation: 77778
Github: Follow along on Github
The following code can take work with all sorts of input names; and handle them just as you'd expect.
E.g.,
<!-- all of these will work! -->
<input name="honey[badger]" value="a">
<input name="wombat[]" value="b">
<input name="hello[panda][]" value="c">
<input name="animals[0][name]" value="d">
<input name="animals[0][breed]" value="e">
<input name="crazy[1][][wonky]" value="f">
<input name="dream[as][vividly][as][you][can]" value="g">
// output
{
"honey":{
"badger":"a"
},
"wombat":["b"],
"hello":{
"panda":["c"]
},
"animals":[
{
"name":"d",
"breed":"e"
}
],
"crazy":[
null,
[
{"wonky":"f"}
]
],
"dream":{
"as":{
"vividly":{
"as":{
"you":{
"can":"g"
}
}
}
}
}
}
$('#my-form').serializeObject();
(function($){
$.fn.serializeObject = function(){
var self = this,
json = {},
push_counters = {},
patterns = {
"validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
"key": /[a-zA-Z0-9_]+|(?=\[\])/g,
"push": /^$/,
"fixed": /^\d+$/,
"named": /^[a-zA-Z0-9_]+$/
};
this.build = function(base, key, value){
base[key] = value;
return base;
};
this.push_counter = function(key){
if(push_counters[key] === undefined){
push_counters[key] = 0;
}
return push_counters[key]++;
};
$.each($(this).serializeArray(), function(){
// skip invalid keys
if(!patterns.validate.test(this.name)){
return;
}
var k,
keys = this.name.match(patterns.key),
merge = this.value,
reverse_key = this.name;
while((k = keys.pop()) !== undefined){
// adjust reverse_key
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// push
if(k.match(patterns.push)){
merge = self.build([], self.push_counter(reverse_key), merge);
}
// fixed
else if(k.match(patterns.fixed)){
merge = self.build([], k, merge);
}
// named
else if(k.match(patterns.named)){
merge = self.build({}, k, merge);
}
}
json = $.extend(true, json, merge);
});
return json;
};
})(jQuery);
Upvotes: 9
Reputation: 413737
You could use ".serializeArray()", and then fix the result:
var json = {};
$.each($('form').serializeArray(), function() {
json[this.name] = this.value;
});
Of course you might want to worry about multi-valued fields:
var json = {};
$.each($('form').serializeArray(), function() {
var cur = json[this.name];
if (cur !== undefined) {
if ($.isArray(cur))
cur.push(this.value);
else
json[ this.name.replace(/\[[^\]]*\]$/, '') ] = [ cur, this.value ];
}
else
json[this.name] = this.value;
});
(edit — now that I think about it, "serialize" and "serializeArray" already kind-of deal with multi-value parameters for you, giving you names like "whatever[2]" in the serialized form. It'd work anyway but it might be unnecessary to do anything more than the simple one.)
Upvotes: 6
Reputation: 7957
I always do it like this, maybe a bit long winded but it's easy for me to maintain.
function FormContent(foo, hello, animals)
{
this.Foo = foo;
this.Hello = hello;
this.Animals = animals;
}
var animals = [];
$("[name='animals[]']").each(function(){
animals.push($(this).val());
});
var foo = $("[name='foo']").val();
var hello = $("[name='hello']").val();
var formContent = new FormContent(foo, hello, animals);
var jsonContent = json.stringify(formContent); // from json.org
I just realized you specifically asked "using jQuery" sorry. I've never had luck serializing to json with jQuery. Hope this helps anyway.
Upvotes: 0