Skip to main

Cleaner way of dealing with query params using URLSearchParams

3 min read

Ever had a situation where you are supposed to convert an object (key, values) into a query parameter and build a URL around it?

Here’s an example:

let user = {
  name: "John Doe",
  age: 24,
};

Let’s say the URL that we want to build / API requires the fields of the above object to be as ?name=..&age=...

The most straightforward way of doing this would be looping through keys of the object and manually appending the key/values to a String while separating each value with an &. Oh and don’t forget to URL encode each value using encodeURIComponent.

For example: John Doe should be encoded as John%20Doe or John+Doe.

let obj = {
  name: "John Doe",
  age: 24,
};

function buildQuery(obj) {
  let query = "";
  Object.entries(obj).forEach(([key, val], currentIndex, entries) => {
    let keyValPair = `${key}=${encodeURIComponent(val)}`;
    if (currentIndex !== entries.length - 1) {
      keyValPair += "&"; // PS: Don't want URLs ending with '&' :)
    }
    query += keyValPair;
  });
  return query;
}

buildQuery(obj);
// Output: "name=John%20Doe&age=20"

You can implement the same with reduce too:

function buildQuery(obj) {
  return Object.entries(obj).reduce(
    (query, [key, val], currentIndex, entries) => {
      let keyValPair = query + `${key}=${encodeURIComponent(val)}`;
      if (currentIndex !== entries.length - 1) {
        keyValPair += "&"; // PS: Don't want URLs ending with '&' :)
      }
      return keyValPair;
    },
    ""
  );
}

// Output: "name=John%20Doe&age=20"

There are other ways of doing this which are more or less similar. But in my opinion, there’s a much cleaner way of dealing with this problem. If you haven’t read the title yet, it is by using URLSearchParams

function buildQuery(obj) {
  let query = new URLSearchParams();
  Object.entries(obj).forEach(([key, val]) => {
    query.set(key, val);
  });
  return query.toString();
}

// Output: "name=John+Doe&age=20"

The set(key,val) method in the URLSearchParams class sets/replaces the key and value into the query whereas append(key, val) appends/adds the key/value into the query. You can use either of those based on the use case;

What about the other way round? What if I have a URL and I want to build an object out of the key/values you ask?

Yep, URLSearchParams has you covered. You can initialize the URLSearchParams constructor with a string i.e query params and loop over it using either forEach loop or the classic for..of loop.

let query = "name=John%Doe&age=20";

function buildUser(query) {
  let params = new URLSearchParams(query);
  let user = {};
  params.forEach((val, key) => {
    user[key] = val;
  });
  return user;
}

// Output: {name: "John Doe", age: "20"}

URLSearchParams also comes with some handy utility functions like has, get, values etc. I encourage you to look it up and read more about it.

Further Reading / References: