Zum Hauptinhalt springen

JSON to Query String

This converter encodes a JSON object as a URL query string in your browser. Nested objects use the a[b]=c bracket convention, arrays repeat their key, values are percent-encoded per RFC 3986 with spaces as %20, and null becomes a key with an empty value. Nothing is uploaded.

Nur lokal

Die Oberfläche dieses Tools ist auf Englisch.

Die folgende Anleitung ist nur auf Englisch verfügbar.

JSON to Query String explained

Every JSON object that has ever travelled as GET request parameters was flattened into a single line of key=value pairs, and the flattening involved choices: how nesting is spelled, how arrays repeat, what happens to null. This converter makes those choices explicit and conventional — objects nest as a[b]=c, arrays repeat their key, and the result is one percent-encoded line, ready to paste after a ?.

None of the conventions were invented here. The bracket style is the one PHP's http_build_query and Ruby on Rails have emitted for two decades, and every serious query-string parser reads it back into structure. Encoding follows RFC 3986: the unreserved characters stay readable, spaces become %20, and a literal plus becomes %2B so it survives both form-mode and strict parsers.

As everywhere on this site, the work happens in the tab that opened the page: your JSON is parsed and encoded by in-page code, and nothing crosses the network. The Content-Security-Policy forbids outbound connections outright, so DevTools' Network panel staying empty while you convert is the whole privacy claim, demonstrated rather than asserted.

The string this page builds is exactly what the sibling converter on the site can decode it back to JSON so a round trip is a good sanity check before the URL ships.

If you only need to escape a single value rather than structure a whole object, the standalone URL encoder and decoder handles one string at a time under the same RFC 3986 rules.

How the encoding actually works

The converter walks the parsed object in key order and emits one pair per element, joined with &. Each value is stringified before encoding — numbers as plain digits, booleans as true or false, null as an empty value — and then percent-encoded as UTF-8. The structure rules are:

  • Objects: a nested object extends the key path with brackets. {"user": {"name": "Ada"}} becomes user[name]=Ada, and a deeper level appends another bracket group: user[address][city]=London.
  • Arrays: an array of scalars repeats its key once per element — tag=navy&tag=math — the style Rack and Node's qs parser read back into arrays.
  • null: becomes a key with an empty value (token=), which keeps the key present in the URL rather than dropping it.
  • Empty objects and arrays: emit nothing for that key, because there is no pair to write; the key's absence is reported in the preview so it is a decision, not a surprise.

Percent-encoding, RFC 3986 style

RFC 3986 leaves the unreserved set — A–Z, a–z, 0–9, hyphen, dot, underscore and tilde — exactly as written and requires everything else to be percent-encoded byte by byte as UTF-8. A space is %20, not +. The plus-for-space habit belongs to application/x-www-form-urlencoded, an older form convention that still causes real bugs: a strict RFC 3986 reader decodes a bare + as a literal plus sign. Emitting %20 for spaces and %2B for pluses means the output means the same thing to both kinds of reader.

One deliberate exception: the square brackets in keys are emitted literally, because that is what the a[b]=c convention looks like in the wild — PHP and Rails do not escape them either. Brackets are structure, not content. Values are strictly encoded, and the reverse decoder on this site accepts both literal and %5B/%5D-escaped brackets.

What the output looks like

The worked example below is the exact pair the Load sample button produces: search parameters with a nested user object, a repeated tag key and a null token. Key order follows the JSON document, so re-encoding a re-parsed string is stable — the same object always produces the same URL, which matters when you are diffing links, caching or writing tests against them.

Edges this converter refuses rather than mangles

Two shapes have no honest encoding under these conventions, and both are rejected with a named error instead of a creative guess:

  • A top-level array — a query string has no keyless slot. Wrap the array in an object under a key, and the repeat convention does the rest.
  • Arrays of objects — tag[name]=a&tag[name]=b would collapse two records into one key path, and inventing indices like tag[0][name] adds structure you never asked for. The converter refuses and names the offending key.

Frequently asked questions

Does converting JSON to a query string upload my data anywhere?

No. The JSON is parsed and encoded entirely inside this browser tab; the page ships no upload endpoint, and its Content-Security-Policy forbids connections to anywhere else, so exfiltration is structurally impossible rather than merely promised. Verify it in thirty seconds: open DevTools, switch to the Network panel, convert, and watch no request appear.

Why is a space encoded as %20 and not +?

Because plus-for-space is the application/x-www-form-urlencoded convention, while RFC 3986 — the URI grammar itself — requires %20 and treats a literal + as a plus sign. Encoding %20 and %2B unambiguously means form-mode and strict parsers decode your value identically. Browsers are lenient either way; the risk is the strict reader in a signed URL or a caching layer, which is exactly where ambiguity is expensive.

Why does nesting use the a[b]=c notation?

It is the de-facto standard bracket spelling, emitted by PHP's http_build_query and Ruby on Rails for two decades and parsed back into nested structure by libraries such as qs (Node) and Rack (Ruby). Alternatives exist — dots, colons, repeated deep keys — but none has remotely the reader support, and an interchange format should optimise for the widest audience.

How are arrays encoded, and why no tag[] spelling?

Arrays of scalars repeat the key: tag=navy&tag=math. Servers such as Rack and Node's qs collect repeated keys into arrays on parse, so the round trip is clean. The exception is PHP, which needs tag[] to build an array — a spelling this converter never emits, because square brackets are reserved for object nesting here. If PHP is the destination, append the empty brackets to the key after converting.

What do null, booleans and numbers become?

null becomes a key with an empty value — token= — which keeps the key present in the URL. Booleans become the literal text true or false, and numbers become plain decimal digits with no locale formatting and no thousands separators. The empty string also becomes an empty value; a query string cannot distinguish it from null, and the reverse decoder reads an empty value back as null by design.

Which characters are left unencoded?

Exactly RFC 3986's unreserved set: A–Z, a–z, 0–9, hyphen, dot, underscore and tilde. Everything else — spaces, ampersands, slashes, accented letters, emoji — is percent-encoded byte-wise as UTF-8. The square brackets in keys are the single visible exception, emitted literally because they are the nesting convention itself; values never receive that treatment.