BlogNode.js

Parsing booleans in Express URL query parameters

Written by Codemzy on September 20th, 2023

When you send a query string `req.query` back to Express, true and false booleans are converted into strings. Here's why, and how I parse them back to booleans - but only sometimes!

I've lost count of the times I've gone crazy over booleans in Node.js. I'll be sending something back to my server like:

GET /api/people?search=false

And on the server, if there is a search parameter, like search=paul then we would search people called paul and send that list back. So we could have something like this in Node.js with Express:

const express = require('express');
const app = express();

app.get('/api/people', (req, res) => {
  const { search } = req.query;
  if (search) {
    res.send(`Searched for ${search}`);
  }
  res.send('All the people!')
});

So why when I'm sending false am I getting a search for people called false?!

"Searched for false"

Surely if (search) { shouldn't be true if it's false?

Well... it shouldn't. If false was a boolean. But it's a string!

In this blog post, we will look at:

  • Why do true and false become strings in Express?
  • How to fix it by not sending false (undefined to the rescue!)
  • How to fix it by converting some parameters to booleans (when you know they need to be booleans)
  • How to fix it by converting all "true" and "false" strings to booleans (and why you might not want to)

Why are true and false booleans converted to strings in Express?

They are not converted to strings in Express. They are converted to strings in the GET request.

When you send false back in the URL string as a GET request, it's sent as a string (and it's the same with true).

And Express doesn't parse it back to a boolean.

Since it's now the string "false", it's a truthy value. This means if (search) { is true and the if block will run and search for people named false.

Why I don’t convert all true and false strings to booleans

You can get Express to parse all of your booleans back to booleans. And that would solve the problem, right? Well, there's a reason why this isn't the default in Express. It's explained more in this GitHub issue for the qs library (which is used by default in Express for parsing query strings).

And I tend to agree in general that it shouldn't be done by default.

What if you take user input somewhere, like a name input? And the user enters true. Should that be parsed to a boolean? No, because the name input should be a string. And some people do have the name True. And some people have the surname True.

I didn't find any records for the first name False, but some people do have the surname False.

Or what if you ask users to submit their pet's name, and they type false? That shouldn’t be a boolean either. Maybe it should be boolean and they just typed false because they don’t have a pet. But that's an assumption. Maybe their pet is called false, and it should be a string.

Either way, since they inputted a string, it should stay a string to be consistent for validation, future updates, etc.

So here are three solutions, which you can choose from depending on your needs and different use cases.

Don't send false parameters (leave them undefined)

Firstly, do you need to send false at all? I've often found the best fix in my code is to not send false. The absence of that parameter is false.

Let's go back to my earlier example.

If there's a search, I need to send the search string back in the GET request.

GET /api/people?search=jane

But if there's not a search, why not just not send the parameter?

GET /api/people

If it's an empty string - don't send the parameter! If it's false - don't send the parameter! If it's null or any other falsy value* - don't send the parameter!

*Maybe not if it's 0 and you need that data, but you get the idea!

Now if we don't send the parameter, it will be undefined on the server. Which is a falsy value (unlike the "false" string we were getting before) - so our if (search) { block won't run when there's no search to do!

That's all well and good if you control the front end. But let's say you have an API that other people send requests to. They might send false in a request, and how are they to realise it will turn into a string?

Convert true and false strings to booleans

If you know a parameter is going to be a boolean, like a checkbox or a toggle or some other true/false parameter, then you can convert that parameter to a boolean yourself.

Here's a simple function you can use:

// converts boolean strings to booleans
function parseBoolean(string) {
  return string === "true" ? true : string === "false" ? false : undefined;
};

Let's go back to my people GET request that returns a list of people. And add an optional active parameter. If active is true, it only returns people who have been active on your service within the last month. If active is false, it only returns people who haven't been active in the last month. And if we leave it undefined then it doesn't filter by active status at all.

GET /api/people?active=true

Here's how we can use the function:

const express = require('express');
const app = express();

app.get('/api/people', (req, res) => {
  const active = parseBoolean(req.query.active);
  if (active) { // only seach active people
    // ...
  }
  res.send('All the people!')
});

My parseBoolean function will always turn the parameter into a boolean, or undefined if it's not. This works for me because I try to make sure my parameters are either booleans or strings. So anything I'm parsing through the parseBoolean should be true, false or undefined.

If you have a parameter that could be true, false or a string, you could do something like this instead:

// converts boolean strings to booleans
// or returns original value
function parseBoolean(value) {
  let bools = {
    true: true,
    false: false,
  };
  return typeof bools[value] === "boolean" ? bools[value] : value;
};

Which will return true or false or the value if it's not a "true" or "false" string.

👆When I first built that function, I returned bools[value] || value, but that only converted true, because of course, false is a falsy value so the OR conditional moved onto the right and returned the original "false" string! Oops!

Parse booleans in all query params

I don't do this, I just parse those parameters that I know should be booleans (and I've explained why above). But that doesn't mean you shouldn't.

Once you have considered the risks* (that in a small amount of cases, you might want "true" or "false" as a string).

*And I would be especially careful of converting all numbers to numbers, as sometimes you might need numbers as strings, for example, currency amounts formatted as strings.

You can use express-query-boolean to do it.

const boolParser = require('express-query-boolean');
app.use(boolParser());

Or you can add your own parser to qs (which Express uses by default to parse query strings). This will convert "true" and "false" values to booleans in all your query strings.

const express = require('express');
const app = express();
const qs = require('qs');

app.setting('query parser', function (str) {
  return qs.parse(str, {
    decoder: function (str, defaultDecoder, charset, type) {
      let bools = {
        true: true,
        false: false,
      };
      if (type === 'value' && typeof bools[str] === "boolean") {
        return bools[str];
      } else {
        return defaultDecoder(str);
      }
    }
  })
});