axios: Why are null and undefined variables removed from params

https://github.com/axios/axios/blob/638804aa2c16e1dfaa5e96e68368c0981048c4c4/lib/helpers/buildURL.js#L38

I would expect

let a
let b
axios({ params: { a, b })

To construct ?a=&b=

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 8
  • Comments: 52 (4 by maintainers)

Commits related to this issue

Most upvoted comments

All of these are possible: { key: undefined } to ? (not included) { key: null } to ?key { key: '' } to ?key= { key: 'null' } to ?key=null

The current behavior is actually in line with how JSON values are handled in JavaScript: JSON.stringify({ a:1, b:undefined, c:2 }) produces {"a":1,"c":2}

{a: undefined} is often used as a construct to ignore a JSON key. If you need “a=” then ‘’ seems to be semantically good enough.

Maybe {a: null} should be interpreted as “?a” param? But not undefined.

Looks like this still hasn’t made it into release yet, damn. Any news on getting v1 released? Probably won’t be relevant anymore, too many years behind. Should have at least added an option to 0.21 that allows you to enable null values, there, no breaking changes!

Its the right behaviour, more strictly it should actually generate something as file?keythathasnullvalue without equal sign and value. It would be wrong to assume an empty string as value. In order to achieve your desired result you have to assign an empty string to it.

What about a web APIs which expects a payload parameter to be explicitly set to null? Some APIs enforce strict type checking rules and do not accept an empty string as a substitute for null.

In my opinion, axios should not remove parameters with null value from the payload.

Five years still counting…

I mean, nobody’s stopping anyone from creating a workaround as a package.

I am already using a workaround, still, I think that it should be an option you can just turn on if you prefer.

I mean, who doesn’t? But I do believe this has to do more with economics.

Why cover everything in one product when you can have other developers extend functionality for you? Just the same reason why axios doesn’t have native cookie jar support, but request (depreciated) does.

@vuoriliikaluoma this seems good, sorry I see I merged it to that v1 branch, I will merge it into master as v1 will release from there. Thanks for your contribution, I know it has been long but I am working hard to get as many features into the v1 release so that we can start with a clean slate for axios/next.

Just wasted 30 minutes of debugging to discover that axios deletes fields with empty strings (“”) in the payload. If that’s not a bug I don’t know what is.

Actually axios interceptor can do the trick. I faced same scenario where json payload contained undefined or null values to be passed to an API as empty string.

I added an interceptor as below snippet. This also works for nested object 😉 thanks recursion!

/**
 * Add json cleaner to set undefined/null values to empty string.
 * This is to prevent axios(json to string using jsonify) from removing those keys
 * when converting json paylod to string.
 */
function cleanJSON(json) {
    for (let key in json) {
        if (json[key] === undefined || json[key] === null) {
            json[key] = '';
        } else if (typeof json[key] === 'object')
            json[key] = cleanJSON(json[key]);
    }
    return json;
}
// Add a request interceptor
window.axios.interceptors.request.use(
    function(config) {
        if (['post', 'put', 'patch'].includes(config.method)) {
            config.data = cleanJSON(config.data);
        }
        return config;
    },
    function(error) {
        return Promise.reject(error);
    }
);

Is the {a: null} to ?a conversion acceptable? If so I’ll try implementing this and creating a pull request.

I mean, nobody’s stopping anyone from creating a workaround as a package.

I am already using a workaround, still, I think that it should be an option you can just turn on if you prefer.

@mrjackyliang Hard disagree. Keys with no values are and always have been a valid part of the HTTP spec. This intervenes and breaks otherwise valid functionally. That’s incorrect behavior and always has been.

In what way? Can you give an example of your use case?

Under HTTP spec, keys with no values are valid, but if you’re trying to convert null or undefined under the JS perspective as a way to represent an empty string under the HTTP spec, where is the connection in that?

However, nobody is stopping you from putting an empty string as a value, in which, is correct from how I see it, and HTTP params are of string type.

?pets=6&hasCats

^ That’s a valid HTTP param line that’s been accepted by servers all over the Internet since always. The hasCats key should come through to the server bag untouched. This has nothing to do with null. It’s about Axios inserting its own opinion about parameter bags that should otherwise be valid in any other context. Again, this is incorrect behavior that does not adhere to the HTTP spec.

Axios is proactively taking an action (removing the key from the parameter bag) that the developer doesn’t intend and the server would not have an issue with. That’s what we’re talking about and always have been talking about.

is there any progress?

Closing due to merge of #1987

@abodelot by payload and its null-handling, are we still talking about the URL parameters, not the POST/PATCH/etc payload?

I’d think {a: null} to ?a conversion is a rather safe solution, and both ?a=null and ?a='null' conversion would potentially cause confusion, requires special handling for the url parser, makes it impossible to send an actual “null” string value…

No, it would generally be used to translate into a Boolean or a state of some kind. /?hasCats the user has cats vs / the user doesn’t have cats. It’s the same outcome as having that value always present and true or false but can save you length on your URL ( browsers don’t allow infinite strong length ) and just prettify your URL. You would check the request for existence of the key rather than it’s value. The point is, it’s valid HTTP, but Axios doesn’t account for it and simply black holes keys with no =. Thus still an open issue afaik.

I actually like the default behavior, since it’s query string:

{ key: undefined } to ? { key: null } to ? { key: ‘’ } to ?key= { key: ‘null’ } to ?key=null

From a strictly typed perspective, only string is a valid query string (see… it’s a self validating statement 😄 )… null and undefined are not strings, nor should axios assume a string representation for them out-of-the-box. Use paramsSerializer config function or interceptors for changing for your use-case.

@abodelot So how do these APIs expect null values to be serialized? As ?foo=null? because in that case, setting { foo: 'null' } would be more appropriate than using actual null.

you can import qs and set paramsSerializer(params){return qs.stringify(params)} to replace default setting.

Passing a key with no value as a URL parameter is a perfectly valid use case.

path?name=Bob&manager

is a valid URL. If no value is passed for the key, it should just leave off the =, but I agree that an empty string is different than null.

@rcbevans If i right understood. He said to pass null as string “null”

@mrjackyliang Sometimes need to pass param=null it means on api that filter by this property which in database null. If you don’t pass then not needed filter this field by null.

4 years after my last comment, and here me on this, I think it’s fair to keep it as is.

I think it goes into the study of what defining “nothing” means, and what axios did here is actually correct.

Took me a long time to figure out why, but it has to do with the understanding of what “void” really means.

If #1987 isn’t good anymore then someone else can give it a go. 😞 It’s been sitting there for 3 years.

That’s not the same thing, and we’re not talking about serialization. ?myKey is valid, and not the same as ?myKey=

@PeterDKC Very true. I think what axios is trying to do is balance the differences between an object vs params format.

If a key includes the = or doesn’t, the URL works regardless (unless URI RFC mandates this requirement). Honestly, I do hate that danging = sign, but I have chosen to just accept the fact even if I don’t like it. Took me quite a bit of time to accept it.

Is passing a query string parameter (whose value is null) without the equals sign valid?

Why wouldn’t you just allow anything to be send as the key? I think it’s pretty ridiculous to remove false or null keys given the prevalence of JSON APIs. If I want to send { “name”: “bob”, “display_phone”: false } it removes “display_phone”. Unacceptable.

You may be confusing query strings with body payload here. The object in question will be serialized into a query string. Using a literal "false" in a query string is seldomly seen as its pretty verbose, and needlessly so - a single "0" would suffice.
Now, the actual problem is that we need a way to submit empty query string keys like ?foo without an assigned value.
The PR by vuoriliikaluoma takes care of this and should be merged soon 😃

Why wouldn’t you just allow anything to be send as the key? I think it’s pretty ridiculous to remove false or null keys given the prevalence of JSON APIs. If I want to send { "name": "bob", "display_phone": false } it removes “display_phone”. Unacceptable.

Pull request is up. (#1987) It was a pretty simple edit.