Bug Tracker

Ticket #8653 (closed bug: fixed)

Opened 4 years ago

Last modified 3 years ago

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
Blocking: Blocked by:

Description (last modified by rwaldron) (diff)

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.

Given

jQuery.param({"string":"foo","null":null,"undefined":undefined})

the output is

"string=foo&null=null&undefined=undefined"

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

My expected output would be:

"string=foo&null=&undefined"

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

comment:1 Changed 4 years ago by d@…

Working example:  http://jsfiddle.net/YuWXy/

comment:2 Changed 4 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 4 years ago by jaubourg

  • Priority changed from undecided to low
  • Component changed from unfiled to ajax

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 4 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 4 years ago by addyosmani (previous) (diff)

comment:5 Changed 4 years ago by addyosmani

  • Status changed from new to open

comment:6 Changed 4 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 4 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 4 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 3 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 3 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 3 years ago by dmethvin

  • Keywords 1.8-discuss added; 1.8=discuss removed

comment:12 Changed 3 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 3 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 3 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 3 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 3 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 3 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 3 years ago by jzaefferer

  • Description modified (diff)

+1

comment:19 Changed 3 years ago by timmywil

+1

comment:20 Changed 3 years ago by rwaldron

  • Description modified (diff)

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

comment:21 Changed 3 years ago by sindresorhus

#11329 is a duplicate of this ticket.

comment:22 Changed 3 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 3 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 15.4.4.5). 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 3 years ago by dmethvin

  • Milestone changed from 1.next to 1.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 3 years ago by tks2103

submitted pull request for behavior as outlined in comment 3:

 https://github.com/jquery/jquery/pull/714

comment:26 Changed 3 years ago by rwaldron

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:

foo=bar&baz&huh=what-the

comment:27 Changed 3 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 3 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 3 years ago by tsinha

  • Status changed from open to closed
  • Resolution set to fixed

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

Changeset: 36d2d9ae937f626d98319ed850905e8d1cbfd078

Note: See TracTickets for help on using tickets.