Cleaner way of dealing with query params using URLSearchParams
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: