Bug Tracker

Opened 12 years ago

Closed 11 years ago

#8653 closed bug (fixed)

jQuery.param outputs "null" and "undefined" in the query string

Reported by: d@… Owned by:
Priority: low Milestone: 1.8
Component: ajax Version: 1.5.1
Keywords: 1.8-discuss Cc: dmethvin
Blocked by: Blocking:

Description (last modified by Rick Waldron)

This ticket is a followup to the discussion in http://forum.jquery.com/topic/should-null-be-passed-in-query-strings-generated-by-jquery-param where I am using jQuery.ajax to send data to a web service.



the output is


which the server will interpret as the strings "null" and "undefined" rather than as empty values.

My expected output would be:


where null values are coerced to empty string, and undefined values have no value. (This is the behaviour in Prototype 1.7, which seems reasonable.)

Change History (29)

comment:1 Changed 12 years ago by d@…

comment:2 Changed 12 years ago by addyosmani

Thanks for submitting a ticket to the jQuery Bug Tracker!

In my opinion, the current behavior is correct and .param() should not be expected to automagically reassign values being passed to it. As per kboudloche, I too don't think the scenario referenced is something a lot of people run into either.

comment:3 Changed 12 years ago by jaubourg

Component: unfiledajax
Priority: undecidedlow

I beg to differ with addy here.

null and undefined are perfectly acceptable values for input data. Their meaning is quite obviously: "in the structure, yet empty"... and the only way to express that in a query string is with an empty parameter.

Current behaviour is not correct: a parameter with values null or undefined will be serialized the same as "null" or "undefined" (string) which is wrong imo.

Not sure I agree with the original poster regarding the solution... I would expect: string=foo&null. That way, people have a mean to prevent serialization (undefined) and a mean to transmit empty values (null).

While you can always pass an empty string, do we really want people to inspect their data structure prior to giving to serialize just to clean up nulls and undefineds and replace them with an empty string? Not sure I do knowing code calling serialize can have very good reasons to differentiate between null and "" internally.

comment:4 Changed 12 years ago by addyosmani

With respect to us expecting users to inspect their data structures prior to serialization, I don't think it's completely unreasonable but.. I'm all for making things as easy as possible to use. I could get down with a string=foo&null solution as jaubourg suggests.

Keeping this open for now to allow dmethvin an opportunity to comment. He was more closely tied in with the discussions on the forum and may have some further insights.

Last edited 12 years ago by addyosmani (previous) (diff)

comment:5 Changed 12 years ago by addyosmani

Status: newopen

comment:6 Changed 12 years ago by gnarf

This has returned this result for a LONG time and changing it would probably break somebody's application.

There was a stack overflow question http://stackoverflow.com/questions/1403963/getjson-call-with-null-parameters-to-mvc-controller-action/1404053#1404053 a while ago that has an answer equally applicable to "fixing" this bug for yourself. Nowadays you could probably even use an ajaxPrefilter (unless you are calling $.param() manually) .

In my opinion, it boils down to asking why you are passing null/undefined data as url parameters in the first place...

comment:7 Changed 12 years ago by addyosmani

Cc: dmethvin davemethvin added

CC'ing davemethvin for his thoughts in case he hasn't reviewed this as yet.

comment:8 Changed 12 years ago by d@…

When a property is set to undefined, hasOwnProperty still returns true, so I'm not sure about skipping them while writing out the query string.

Removing the = would cause me problems. I am calling an asp.net WebMethod which selects which handler to use based on keys in the query string, but it ignores parameters without an =. With the "string=foo&null" solution, a call to jQuery.ajax(webMethodUrl, { data : { key : value } }) may or may not call the web method at webMethodUrl, since the = might be missing. I would be back to checking each data object in ajaxPrefilter, and the change could break existing code.

Writing out empty string for null and undefined, "string=foo&null=&undefined=", would be safer.

comment:9 Changed 12 years ago by oliver.dungey@…

+1 for a change in this area. I have just bumped into this with a Java RESTful backend (Jersey) whereby the server side is expecting a UUID or null but it is getting a string of "null" or "undefined", both of which are a problem as it is sending a string instead of a null. From my point of view the fix is either:

  1. don't bother sending null values at all (on the basis that null = nothing to send).
  2. send "parameter="

The only workaround I have at the moment is to put null checks before pushing in each parameter which is very verbose.

comment:10 Changed 12 years ago by dmethvin

Cc: davemethvin removed
Keywords: 1.8=discuss added

Are there any fans of the current behavior? I suppose the problem is that none of them will arrive to defend it until we change it.

comment:11 Changed 12 years ago by dmethvin

Keywords: 1.8-discuss added; 1.8=discuss removed

comment:12 Changed 12 years ago by smart@…

According to http://tools.ietf.org/html/rfc3986, the "%00" percent-encoding *could* be used. Nowhere does it say anything about using the string "null" for null values. Clearly, as URL is an encoding, the current behavior is broken.

comment:13 Changed 12 years ago by exxizt@…

This behaviour is definitely not right. I'm sure many are eager to see it fixed.

For those interested, this is the part from SO answer that removes the properties that are set to null:

function stripNull(obj) {
  for (var i in obj) {
    if (obj[i] === null) delete obj[i];
  return obj;

comment:14 Changed 12 years ago by Douglas <rampant@…>

exxizt: stripNull removes null properties from an object, but jQuery.param should not modify the object passed in. The solution proposed by jaubourg in comment 3 still appears to be the correct one.

comment:15 Changed 11 years ago by mikesherov

Description: modified (diff)

+1, This makes sense, and I'm not sure who would rely on this buggy behavior.

comment:16 Changed 11 years ago by jaubourg

+1, we just need to iron out what the fix is (see my comment #3). Current behaviour doesn't make sense and I shudder to think who would rely on it.

comment:17 Changed 11 years ago by dmethvin

Description: modified (diff)

+1, I am not a fan of the current behavior. I think we should totally skip undefined values and use "name=" for the null case.

comment:18 Changed 11 years ago by jzaefferer

Description: modified (diff)


comment:19 Changed 11 years ago by Timmy Willison


comment:20 Changed 11 years ago by Rick Waldron

Description: modified (diff)

+0, I've never experienced an issue with this... wouldn't it break BC?

comment:21 Changed 11 years ago by sindresorhus

#11329 is a duplicate of this ticket.

comment:22 Changed 11 years ago by wardrop

By my duplicate ticket above, I clearly agree. The only types a controller for a web application should care about, is String - there's no place or need for sending the variable state, plus it means any server-side passing of null and undefined values would mean that any user that inputs these string values ("null" and "undefined") would not get the result they expected. An empty string communicates a undefined/null/empty/default value. The exact meaning of an empty string depends on the controller that handles it.

I think not fixing for the sake of backwards compatibility is a poor excuse. First of all, I'm of the opinion that anyone that depends on this behaviour ought to have their application break (nasty, I know), but more importantly, no one should be upgrading jQuery on a production application and expect it to work every time. The sooner this is changed, the less of a pain it will be in the future.

In the meantime, I've overridden the built-in encodeURIComponent function to return empty strings for null and undefined. This is what jQuery uses that results in the "null" and "undefined" strings.

comment:23 Changed 11 years ago by Douglas <rampant@…>

Array.prototype.join sets a precedent for treating null and undefined as empty strings while serialising a structure to a string (EMCA spec The param utility should behave in the same way since the use case is so similar.

The trade off on the receiving end is either to be able to distinguish null and undefined, or to be able to distinguish null from the string "null". The latter appears to be more useful.

comment:24 Changed 11 years ago by dmethvin

Milestone: 1.next1.8

I'm not sure why there's so much activity on this ticket now. The ticket is open and has been voted for action in 1.8. There is no need for further discussion on this unless you are one of these people and want to retain the current behavior.

comment:25 Changed 11 years ago by tks2103

submitted pull request for behavior as outlined in comment 3:


comment:26 Changed 11 years ago by Rick Waldron

On github you also cited http://bugs.jquery.com/ticket/8653#comment:17 - so which is it? The missing = just looks odd, as it breaks the notion of key = val. Especially in this context:


comment:27 Changed 11 years ago by tks2103

reasoning for "key" over "key=" in the null case is that "key=" does not distinguish empty string from null case. thats why i favored "key".

comment:28 Changed 11 years ago by dmethvin

I discussed with tks2103 and we're just going to turn null/undefined into empty strings, the behavior advocated by @Douglas above. It's the simplest and smallest to implement. Trying to distinguish between special values is not advisable, the main use case of jQuery.param is to take a form element value and serialize it, these cases are not defined.

comment:29 Changed 11 years ago by tsinha

Resolution: fixed
Status: openclosed

Fix #8653, .param() undefined/null values become empty strings

Changeset: 36d2d9ae937f626d98319ed850905e8d1cbfd078

Note: See TracTickets for help on using tickets.