Skip to content

Query String

The parse/serialize half of every URL-driven feature — filters, sorts, pagination, search forms — packaged as one default export. Pass it an object, get back a query string with [] array brackets and [parent][child] nesting. Pass it a query string, get back an object with numeric coercion applied. Four browser-bound methods (all, get, update, toString) read and write window.location; the two pure data methods (parse, toQueryString) work anywhere.

Highlighted features

Nested object + array shapes

?tags[]=a&user[name]=alice{ tags: [“a”], user: { name: “alice” } }. Any depth, both directions.

Numeric coercion on parse

”page=2” parses as { page: 2 } — the number, not the string. Lossy by design: “007”7.

No-reload URL rewriter

queryString.update({…}) rewrites window.location.search via history.replaceState — no reload, no popstate fire.

Zero deps, SSR-safe parsers

The two pure methods (parse, toQueryString) work in browser, Node, and edge workers. Browser-only methods are clearly demarcated.

Install

Terminal window
npm install @mongez/query-string

Zero runtime dependencies.

Quick peek

import queryString from "@mongez/query-string";
queryString.parse("?page=2&tags[]=a&tags[]=b&user[name]=alice");
// → { page: 2, tags: ["a", "b"], user: { name: "alice" } }
queryString.toQueryString({ page: 2, tags: ["a", "b"] });
// → "page=2&tags[]=a&tags[]=b"
queryString.update({ tag: "books", page: 1 });
// window.location.search becomes "?tag=books&page=1" — no reload

Parse and serialize with array + nested-object support, plus a no-reload URL rewriter for browser code.

Mental model

ConceptTypeMental model
parse / toQueryStringpure functionStateless conversion between Record<string, any> and string. Same in browser and server.
all / get / toStringbrowser readSugar over parse(window.location.search).
updatebrowser writeSugar over history.replaceState.
Numeric coercionparse-timeValues matching !isNaN(v - parseFloat(v)) become numbers. Lossy: "007"7.
Array shapeURL conventionkey[]=a&key[]=b{ key: ["a", "b"] }.
Object shapeURL conventionparent[child]=v{ parent: { child: v } }. Any depth.

Environment

  • Browser: every method works.
  • Server / Worker: parse and toQueryString are safe. all / get / toString / update reference window.location / window.history and will throw. Guard with typeof window !== "undefined" if the same module loads on both sides.

Idioms

  • Call update from event handlers, not effects. It’s a deliberate side effect on browser history; running it in a useEffect makes the URL flip on every render.
  • Don’t trust get(key, default) for falsy values. Use key in queryString.all() if you need a presence check.
  • Pass raw strings to the serializer. toQueryString runs values through encodeURIComponent for you — pre-encoding double-encodes.
  • Use update({}) to clear the query string. It rewrites the URL to just the pathname.
  • update does not fire popstate. If you mirror URL state into another store, subscribe to your store, not popstate.

Where to go next

  • Parse — input shapes, coercion rules, edge cases
  • Serialize — output shapes, encoding rules
  • Recipes — common patterns