Decode URLs with the query string to JSON parser
This query string to JSON tool reads the parameters of a URL and turns them into a structured JSON object. It decodes percent-encoding and + spaces, collects repeated keys into arrays, and understands the bracket notation used by PHP, Rails, Express's qs and jQuery's $.param, so filter[price][max]=120 becomes a nested object instead of a key full of brackets.
Example
https://shop.example.com/search?q=running+shoes&size=42&color[]=red&color[]=blue&filter[brand]=acme&filter[price][max]=120&page=2#results
Output with the default options:
{
"q": "running shoes",
"size": "42",
"color": ["red", "blue"],
"filter": {
"brand": "acme",
"price": { "max": "120" }
},
"page": "2"
}
The scheme, host, path and #results fragment are ignored; only the query is parsed. That makes it easy to inspect a long tracking link, a search results URL or a redirect captured in your browser's network panel.
Supported syntaxes
- Repeated keys:
tag=a&tag=bgives"tag": ["a", "b"], the way most frameworks read them. - Empty brackets:
color[]=red&color[]=bluealways produces an array, even with one item. - Indexed arrays of objects:
items[0][sku]=MUG&items[0][qty]=2&items[1][sku]=CAPbuilds[{"sku": "MUG", "qty": "2"}, {"sku": "CAP"}]. - Keys without values:
flagandempty=both give an empty string. - Semicolons are accepted as separators as well as
&.
How servers read the same query
The JSON here follows the common bracket conventions, but back ends do not agree on everything, especially repeated keys without brackets:
| Reader | tag=a&tag=b becomes |
|---|---|
PHP $_GET | "b": the last value wins unless the key is written tag[] |
| Express with qs | ["a", "b"] |
Python urllib.parse.parse_qs | {"tag": ["a", "b"]}; every value is a list, even a single one |
JavaScript URLSearchParams | get("tag") returns "a"; getAll("tag") returns both |
If a parameter arrives with only one value on your server, check which of these rules applies before suspecting the client.
Convert numbers & booleans
Off by default, because every URL value is really text, and your server sees strings. Turn it on to get "limit": 10 and "debug": true, which is handy when building test fixtures. Values with leading zeros, such as zip=02134, stay strings either way.
Edge cases
- Encoded brackets like
filter%5Bbrand%5D=acmeare decoded before parsing and still nest correctly. - An encoded plus (
%2B) becomes a literal+, while a bare+becomes a space, per form encoding. - Broken percent-encoding such as
%E0%A4%Ais kept as written instead of failing the whole conversion. - UTF-8 characters are decoded:
Jos%C3%A9becomesJosé.
To break a URL into protocol, host, path and fragment as well, use the URL parser. To go the other way, build a query from an object with JSON to query string, or decode a single value with URL decode.
Privacy
Parsing happens in your browser. URLs often carry tokens, email addresses or session IDs, and none of it is uploaded.