Skip to main content

Bug Tracker

Side navigation

#4201 closed feature (fixed)

Opened February 20, 2009 02:10PM UTC

Closed December 05, 2009 01:52AM UTC

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.

Attachments (0)
Change History (6)

Changed September 02, 2009 05:17AM UTC by yehuda comment:1

resolution: → fixed
status: newclosed

Closed by r6534

Changed September 03, 2009 02:50AM UTC by cowboy comment:2

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?

Changed September 14, 2009 05:18PM UTC by cowboy comment:3

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.

Changed September 16, 2009 08:45AM UTC by yehuda comment:4

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

Changed September 17, 2009 09:59PM UTC by cowboy comment:5

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

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

Changed December 05, 2009 01:52AM UTC by john comment:6

resolution: → fixed
status: reopenedclosed