Bug Tracker

Opened 11 years ago

Closed 10 years ago

#4201 closed feature (fixed)

Improved $.param serialization

Reported by: john Owned by:
Priority: major Milestone: 1.4
Component: ajax Version: 1.3.2
Keywords: Cc:
Blocked by: Blocking:

Description

I've been using it a lot with a Ruby on Rails backend, and one of the things I need was a way to nest params like the way Rails handles forms/objects, eg. with a Page object:

page[name]=Foo&page[author]=Bar

Unfortunately, $.param didnt translate objects this way, but adding just a few simple lines made it work like a charm:

http://gist.github.com/66948

Now:

$.param({page: {name: 'Foo', author: 'Bar'})

Translates to above.

Thought this might be helpful for other people working with Rails/ jQuery and with a little clean up could be a nice addition to core.

Change History (6)

comment:1 Changed 10 years ago by yehuda

Resolution: fixed
Status: newclosed

Closed by r6534

comment:2 Changed 10 years ago by cowboy

Resolution: fixed
Status: closedreopened

I was working on writing the deserialization code for this change into URL Utils this evening, but came across a potential problem.

This scenario is ambiguous at best, but a total mess at worst:

console.log( decodeURIComponent( $.param( { a: [ 1, 2, { b: 3, c: 4 } ] } ) ) );

That outputs a=1&a=2&a[b]=3&a[c]=4 which when deserialized, would probably yield an 'a' param that is an array [1, 2] but that also has .b = 3 and .c = 4. Since JS arrays are also objects, this is of course valid, but unintended.

Now, since it's clear when parsing a=1&a=2&a[b]=3&a[c]=4 that a is an array, perhaps the deserialization code can say 'any object properties from here on are part of a sub-object' .. but then how do we differentiate between { a: [ 1, 2, { b: 3, c: 4 } ] } and { a: [ 1, 2, { b: 3 }, { c: 4 } ] }, or even what do we do when we have { a: [ { b: 3, c: 4 }, 1, 2 ] } which results in a[b]=3&a[c]=4&a=1&a=2 - how does the deserializer even know that a is an array and not an object when it starts parsing?

I have a feeling that the ambiguity introduced in these changes to $.param might cause more harm than good in the long run, especially since we already have JSON for deep objects, and anyone could do $.param( { a: json_string } );

Thoughts?

comment:3 Changed 10 years ago by cowboy

This is my proposed fix for $.param:

http://benalman.com/code/projects/jquery-1.3.3/param.js

Note that I chose to not throw errors, because it was *significantly* less code. I'm more than happy to add that in, but I'm not sure that it's worth it (considering 1.3.2 already does [object Object]).

So, now, if $.param_compat_mode is true, things should work just like before, encoding just scalars and arrays, without any [] in the serialized string. If $.param_compat_mode is false (default), it should work as-intended, but just stringifying array items instead of recursing into them, inside arrays. It seems to me that this approach will solve any re-serialization ambiguity issues, but I'd really like someone else to vet what i've done, just to be sure. I really think that proper testing for param is critical!

Also, I have no idea how you'd want to implement the compatibility mode flag, but i do think that it's really important to put it in there (as deprecated), which might give 1.3.3-param-incompatible library authors time to address their library's limitations.

comment:4 Changed 10 years ago by yehuda

This is just waiting a good name for the flag. John?

comment:5 Changed 10 years ago by cowboy

Here's a legitimate diff with unit tests and everything:

http://benalman.com/code/projects/jquery-1.3.3/param.diff

comment:6 Changed 10 years ago by john

Resolution: fixed
Status: reopenedclosed
Note: See TracTickets for help on using tickets.