In this article, I will explain cover how you can convert a query string into an object and vice versa, which will allow you to easily get and set URL query parameters.
Despite this being a common task, I find myself googling it repeatedly because there isn't only one way of doing it.
But before we start, what is a query string again?
A query string is the part of the URL that comes after the question mark.
When you google something, for instance, you can see your search query in the URL as a query parameter:
https:/search?q=something
When working with URLs, parsing and creating these queries is a common task, which used to require a manual function that parses the string.
Nowadays, however, this is much easier thanks to the URLSearchParams interface, which we'll mainly use in this tutorial.
The browser support of this API is quite good as well. As you can see here, more than 95% of all users are covered.
How to create a query string
When making API requests, we'll typically need to append query parameters to the URL.
With the URLSearchParams
API, we can simply pass an object with the parameters to the class's constructor:
const params = new URLSearchParams({ foo: "1", bar: "2" });
With that done, we now have an instance of the URLSearchParams
class. We can get the string version of this by calling toString
and append this to our URL.
const query = params.toString(); // Output: foo=1&bar=2
const url = `https://thecatapi.com/?${query}`;
Building URLs with the URL
constructor
Creating a URL is easier with the URL
object constructor.
We can set the query to a URLSearchParams
object; fetch
also accepts this object instead of a string.
const url = new URL("https://thecatapi.com/");
// Equals "?breed=aegan&categories=sinks%2Cspace"
url.search = new URLSearchParams({
breed: "aegan",
categories: ["sinks", "space"],
});
const response = await fetch(url);
How to get URL parameters from a query string
Now, what can we do when we want to convert a query string into an object?
Let's say we have an entire URL from which we want to extract the query:
const urlString = "https://thecatapi.com/?breed=aegan&categories=sinks%2Cspace";
We can convert this into an URL object and access the URLSearchParams
object via url.searchParams
:
const urlString = "https://thecatapi.com/?breed=aegan&categories=sinks%2Cspace";
let url = new URL(urlString);
url.searchParams.get("breed"); // "aegan";
The URLSearchParams
interface has some useful functions that allow us to extract data from the URL, such as get, getAll, keys, or has. You can read more about these functions on the MDN Web Docs.
While this should be enough in most cases, we might want to convert this into a regular object anyway.
Convert URLSearchParams to object
There are some use-cases where we'll need to have the search parameters in an object instead of the URLSearchParams
interface.
This great StackOverflow answer helped me achieve this, so credit goes to the author. Give the answer an upvote if it helped you as well!
function paramsToObject(entries) {
const result = {};
for (const [key, value] of entries) {
// each 'entry' is a [key, value] tupple
result[key] = value;
}
return result;
}
This approach works well if we only have primitive values in our query string.
However, issues arise when we want to search queries with arrays.
Parsing URLs with arrays in the search query
Parsing URLs with arrays is a more complex topic because there is no standardized way of defining them in URLs, which means that the URLSearchParams
API doesn't support parsing arrays or objects.
There's a massive number of implementations: Arrays can be defined by repeating the parameter...
?foo=bar&foo=qux
...with square brackets...
?foo[]=bar&foo[]=qux # URL-encoded: ?foo%5B%5D=bar&foo%5B%5D=qux
...or separated by a comma.
?foo=bar,qux
Besides these formats mentioned, there are many more which I can't list here, as each API can implement its own syntax.
The take-away from this is that we either take it into our own hands and create a function that parses the search string according to the implementation, or we use a library that supports most cases (like query-string).
Here's an example of how such a function may look like, implementing the square bracket syntax (e.g. ?foo[]=a&foo[]=b
):
const getQueryParams = (query) => {
let params = {};
new URLSearchParams(query).forEach((value, key) => {
let decodedKey = decodeURIComponent(key);
let decodedValue = decodeURIComponent(value);
// This key is part of an array
if (decodedKey.endsWith("[]")) {
decodedKey = decodedKey.replace("[]", "");
params[decodedKey] || (params[decodedKey] = []);
params[decodedKey].push(decodedValue);
// Just a regular parameter
} else {
params[decodedKey] = decodedValue;
}
});
return params;
};
console.log(getQueryParams("?b[]=1&b[]=2&a=abc&c[]=1"));
{ b: [ '1', '2' ], a: 'abc', c: [ '1' ] }
Parsing other implementations would look similar, however, when dealing with multiple syntaxes, I would highly recommend using the query-string, as it's well-tested and supports most array implementations.
Conclusion
The URLSearchParams
API is now well supported and offers the core functionality needed when manipulating search queries.
However, since objects and arrays are not standardized, it doesn't offer the functionality needed in all cases.
If your application has more advanced use-cases, you should consider using a library or creating your own function for parsing and creating query strings correctly.
If this article was helpful to you, make sure to subscribe to my newsletter to get notified when I release a new article on web development.
Further reading and links
UrlSearchParams API Documentation
The official documentation for the native
URLSearchParams
API.The recommended package for parsing and creating query strings.
JavaScript Event Loop And Call Stack Explained
Do you want to know how JavaScript works behind the scenes? In this post series, I explore what happens when we execute JavaScript in the browser.