RezoURLSearchParams
RezoURLSearchParams provides support for nested objects and arrays in URL query strings. It supports three nesting modes — json, brackets, and dots — and can reconstruct the original nested structure from flat query strings.
import { RezoURLSearchParams } from 'rezo'; Nested Modes
The nestedKeys option controls how nested objects and arrays are serialized:
json Mode (default)
Nested values are JSON-stringified as string values. Simple and universal, but the server must parse JSON strings from query parameters.
const params = new RezoURLSearchParams({
name: 'Alice',
tags: ['admin', 'user'],
address: { city: 'NYC', zip: '10001' },
}, { nestedKeys: 'json' });
params.toString();
// name=Alice&tags=%5B%22admin%22%2C%22user%22%5D&address=%7B%22city%22%3A%22NYC%22%2C%22zip%22%3A%2210001%22%7D
// Decoded: name=Alice&tags=["admin","user"]&address={"city":"NYC","zip":"10001"} brackets Mode
Uses bracket notation compatible with PHP, Rails, Express/qs, and most server frameworks:
const params = new RezoURLSearchParams({
user: {
name: 'Alice',
roles: ['admin', 'editor'],
address: { city: 'NYC' },
},
}, { nestedKeys: 'brackets' });
params.toString();
// user[name]=Alice&user[roles][0]=admin&user[roles][1]=editor&user[address][city]=NYC Note: toString() in brackets mode automatically decodes %5B and %5D back to literal [ and ], matching the convention expected by standard form parsers.
dots Mode
Uses dot notation for nesting:
const params = new RezoURLSearchParams({
user: {
name: 'Alice',
roles: ['admin', 'editor'],
},
}, { nestedKeys: 'dots' });
params.toString();
// user.name=Alice&user.roles.0=admin&user.roles.1=editor Constructor
Accepts all standard URLSearchParams initializers plus nested objects:
// From nested object
const params = new RezoURLSearchParams({ key: 'value' });
// From string
const params = new RezoURLSearchParams('key=value&other=123');
// From array of pairs
const params = new RezoURLSearchParams([['key', 'value']]);
// From another URLSearchParams
const params = new RezoURLSearchParams(new URLSearchParams('a=1'));
// From another RezoURLSearchParams (inherits nested mode)
const params = new RezoURLSearchParams(existing);
// With explicit nested mode
const params = new RezoURLSearchParams(data, { nestedKeys: 'brackets' }); appendObject(obj, prefix?)
Append all keys from a nested object. Use prefix for sub-objects:
const params = new RezoURLSearchParams(undefined, { nestedKeys: 'brackets' });
params.appendObject({
filter: {
status: 'active',
tags: ['important', 'urgent'],
},
});
params.toString();
// filter[status]=active&filter[tags][0]=important&filter[tags][1]=urgent Multiple calls to appendObject accumulate values:
params.appendObject({ page: '1' });
params.appendObject({ page: '2' });
params.toString();
// page=1&page=2 setObject(obj, prefix?)
Like appendObject, but replaces existing values with the same prefix:
const params = new RezoURLSearchParams(undefined, { nestedKeys: 'brackets' });
params.setObject({ filter: { status: 'draft' } });
params.toString(); // filter[status]=draft
params.setObject({ filter: { status: 'published' } });
params.toString(); // filter[status]=published (replaced, not duplicated) When called without a prefix, setObject clears all existing parameters first.
toFlatObject()
Returns a plain object with keys as-is (no nested reconstruction):
const params = new RezoURLSearchParams(undefined, { nestedKeys: 'brackets' });
params.appendObject({ user: { name: 'Alice', age: 30 } });
params.toFlatObject();
// { 'user[name]': 'Alice', 'user[age]': '30' } toObject()
Reconstructs the original nested structure by parsing bracket-notation keys and JSON-encoded values:
// From brackets
const params = new RezoURLSearchParams('user[name]=Alice&user[roles][0]=admin&user[roles][1]=editor');
params.toObject();
// { user: { name: 'Alice', roles: ['admin', 'editor'] } }
// From JSON mode
const params = new RezoURLSearchParams('tags=["a","b"]&config={"debug":true}');
params.toObject();
// { tags: ['a', 'b'], config: { debug: true } }
// Simple key-value pairs pass through
const params = new RezoURLSearchParams('name=Alice&page=1');
params.toObject();
// { name: 'Alice', page: '1' } Array indices in bracket keys are detected automatically ([0], [1], etc.) and produce arrays instead of objects.
fromFlat(obj)
Static factory that creates a RezoURLSearchParams from a flat Record<string, string>:
const params = RezoURLSearchParams.fromFlat({
'user[name]': 'Alice',
'user[email]': 'alice@example.com',
});
params.toString();
// user%5Bname%5D=Alice&user%5Bemail%5D=alice%40example.com Type Handling
RezoURLSearchParams handles these value types:
| Type | Serialization |
|---|---|
string | Used as-is |
number | Converted via String() |
boolean | Converted via String() |
Date | Converted via .toISOString() |
null / undefined | Skipped (not appended) |
Array | Indexed keys (brackets/dots) or JSON (json mode) |
Object | Nested keys (brackets/dots) or JSON (json mode) |
Usage with Rezo
import rezo from 'rezo';
import { RezoURLSearchParams } from 'rezo';
// As query parameters
const params = new RezoURLSearchParams({
filter: { status: 'active', category: 'tech' },
sort: '-date',
page: 1,
}, { nestedKeys: 'brackets' });
const response = await rezo.get('https://api.example.com/posts', {
params,
});
// GET https://api.example.com/posts?filter[status]=active&filter[category]=tech&sort=-date&page=1
// As form body
const response = await rezo.post('https://api.example.com/search', params.toString(), {
headers: { 'content-type': 'application/x-www-form-urlencoded' },
});