How to migrate from querystring to URLSearchParams in Node.js
Written onNode.js marked the querystring as legacy API in version 14.x, and recommends using URLSearchParams. But doesn't give us any clue how to actually migrate. This article fills this void and provides a migration guide.
querystring
querystring API is quite simple and straightforward:
- querystring.parse()
- Parses a URL query string into a collection of key and value pairs. querystring.decode() is an alias.
- querystring.stringify()
- Produces a URL query string from a given obj by iterating through the object's "own properties". querystring.encode() is an alias.
- querystring.escape()
- Performs URL percent-encoding on the given string in a manner that is optimized for the specific requirements of URL query strings. Is used by querystring.stringify().
- querystring.unescape()
- Performs decoding of URL percent-encoded characters on the given string. Is used by querystring.parse().
Parse a URL query string
Produce a URL query string
Perform URL percent-encoding on the given string
Perform decoding of URL percent-encoded characters on the given string
URLSearchParams
What’s the actual difference between querystring
vs. URLSearchParams
?
"The WHATWG URLSearchParams interface and the querystring module have similar purpose, but the purpose of the querystring module is more general, as it allows the customization of delimiter characters."
Working with URIs/URLs in JavaScript was always confusing. WHATWG URL specification finally standardizes the term URL and provides a standardized way how we work with URLs. URLSearchParams is part of this specification. Now let’s migrate our previous querystring examples to URLSearchParams API.
Parse a URL query string
Produce a URL query string
As we can see, what we got is a different result compared to querystring.
API | Result |
---|---|
querystring | foo=bar&baz=qux&baz=quux&corge= |
URLSearchParams | foo=bar&baz=qux%2Cquux&corge= |
"Unlike querystring module, duplicate keys in the form of array values are not allowed. Arrays are stringified using array.toString(), which simply joins all array elements with commas."
To get the result compatible with querystring, we have to initialize URLSearchParams with a list of tuples instead of object:
Perform URL percent-encoding on the given string
There is no low-level API for encoding simple strings in URLSearchParams. We have to be a little creative to achieve URL encoding. Below are 2 different yet functionally equivalent ways how to achieve the same result.
Again, we can see what we got is a different result compared to querystring. WHATWG URL specification
is now precise about how various segments of URL gets encoded. Spaces in query parameters are now plus-sign (+
) encoded,
compared to percent-encoded spaces in the path segment of the URL. This currently accepted behavior is backward incompatible with querystring,
and there is nothing you can do about it except to take it.
API | Result |
---|---|
querystring | str1%20str2 |
URLSearchParams | str1+str2 |
Perform decoding of URL percent-encoded characters on the given string
There is no low-level API for decoding a simple string in URLSearchParams. Again we have to be creative to achieve URL decoding on the given string.
URLSearchParams will handle percent-encoded spaces as well:
Other differences
Handling of question mark character
URLSearchParams removes question mark character from the start of the URL query string. querystring keeps it and makes it part of the key name.
Converting URLSearchParams object to Plain JavaScript Object
URLSearchParams object is a class instance. It is not a classical Plain JavaScript Object (POJO). To transform URLSearchParam instance into a POJO, use the following recipe.
Have you found other differences? I’d be happy to add them to this list.
Closing words
querystring is a legacy Node.js API that shouldn’t be used anymore. New code should only use URLSearchParams, which is part of WHATWG URL specification. Old code using querystring can easily be migrated to URLSearchParams using this guide. The only backward incompatibility between the two APIs is that URLSearchParams use plus-encoded spaces instead of percent-encoded spaces in querystring.