{"id":16328783,"url":"https://github.com/43081j/picoquery","last_synced_at":"2025-04-04T13:04:01.156Z","repository":{"id":245397035,"uuid":"791510872","full_name":"43081j/picoquery","owner":"43081j","description":"A small library for parsing and serializing query strings","archived":false,"fork":false,"pushed_at":"2025-01-07T18:51:56.000Z","size":122,"stargazers_count":87,"open_issues_count":3,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T12:01:43.554Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/43081j.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"43081j"}},"created_at":"2024-04-24T21:06:19.000Z","updated_at":"2025-03-26T06:08:10.000Z","dependencies_parsed_at":"2024-07-26T15:26:15.503Z","dependency_job_id":"c7380be3-4a58-4e42-979f-711cbed81c02","html_url":"https://github.com/43081j/picoquery","commit_stats":{"total_commits":38,"total_committers":3,"mean_commits":"12.666666666666666","dds":0.07894736842105265,"last_synced_commit":"327c7dba1c6b9435e9db726dc8bbb7175f369519"},"previous_names":["43081j/picoquery"],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/43081j%2Fpicoquery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/43081j%2Fpicoquery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/43081j%2Fpicoquery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/43081j%2Fpicoquery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/43081j","download_url":"https://codeload.github.com/43081j/picoquery/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247174423,"owners_count":20896078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T23:14:31.616Z","updated_at":"2025-04-04T13:04:01.138Z","avatar_url":"https://github.com/43081j.png","language":"TypeScript","readme":"# picoquery\n\n[![CI](https://github.com/43081j/picoquery/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/43081j/picoquery/actions/workflows/main.yml)\n[![NPM version](https://img.shields.io/npm/v/picoquery.svg?style=flat)](https://www.npmjs.com/package/picoquery)\n\nA lightweight query string parser/stringifier with support for nesting and some\nconfigurability.\n\nBuilt on top of [fast-querystring](https://github.com/anonrig/fast-querystring).\n\n## Install\n\n```sh\nnpm i -S picoquery\n```\n\n### CommonJS vs ESM\n\n`2.x` and above are _ESM only_ (i.e. your project will need `type: \"module\"`\nin the `package.json`).\n\nIf you cannot yet move to ESM, you may continue to use `1.x` which will still\nreceive non-breaking changes, backported from `main`.\n\n## Usage\n\nParsing a query string:\n\n```ts\nimport {parse} from 'picoquery';\n\nparse('foo.bar=abc\u0026baz=def');\n\n/*\n  {\n    foo: {\n      bar: 'abc'\n    },\n    baz: 'def'\n  }\n*/\n```\n\nStringifying an object:\n\n```ts\nimport {stringify} from 'picoquery';\n\nstringify({\n  foo: {\n    bar: 123\n  }\n});\n\n/*\nfoo.bar=123\n*/\n```\n\n## API\n\n### `stringify(object[, options])`\n\nConverts the given object into a query string, optionally with configured\noptions.\n\n### `parse(str[, options])`\n\nParses the given query string into an object, optionally with configured\noptions.\n\n## Options\n\n### Default options\n\nThe default options are as follows:\n\n```ts\n{\n  nesting: true,\n  nestingSyntax: 'dot',\n  arrayRepeat: false,\n  arrayRepeatSyntax: 'repeat',\n  delimiter: '\u0026'\n}\n```\n\n### `nesting`\n\nWhen true, nested objects are supported.\n\nFor example, when parsing:\n\n```ts\nparse('foo.bar=baz', {nesting: true});\n\n// {foo: {bar: 'baz'}}\n```\n\nWhen stringifying:\n\n```ts\nstringify({foo: {bar: 'baz'}}, {nesting: true});\n\n// foo.bar=baz\n```\n\nThis also results in arrays being supported:\n\n```ts\nparse('foo.0=bar', {nesting: true});\n// {foo: ['bar']}\n\nstringify({foo: ['bar']}, {nesting: true});\n// foo.0=bar\n```\n\n### `nestingSyntax`\n\nSets which style of nesting syntax should be used. The choices are:\n\n- `dot` (e.g. `foo.bar=baz`)\n- `index` (e.g. `foo[bar]=baz`)\n- `js` (e.g. `foo.bar[0]=baz`, i.e. arrays are indexed and properties are\ndotted)\n\n### `arrayRepeat`\n\nIf `true`, this will treat repeated keys as arrays.\n\nFor example:\n\n```ts\nparse('foo=x\u0026foo=y', {arrayRepeat: true});\n// {foo: ['x', 'y']}\n\nstringify({foo: ['x', 'y']}, {arrayRepeat: true});\n// foo=x\u0026foo=y\n```\n\n### `arrayRepeatSyntax`\n\nSets which style of array repetition syntax should be used. The choices are:\n\n- `bracket` (e.g. `foo[]=x\u0026foo[]=y`)\n- `repeat` (e.g. `foo=x\u0026foo=y`)\n\n### `delimiter`\n\nSets the delimiter to be used instead of `\u0026`.\n\nFor example:\n\n```ts\nparse('foo=x;bar=y', {delimiter: ';'});\n// {foo: 'x', bar: 'y'}\n\nstringify({foo: 'x', bar: 'y'}, {delimiter: ';'});\n// foo=x;bar=y\n```\n\n### `valueDeserializer`\n\nCan be set to a function which will be used to deserialize each value during\nparsing.\n\nIt will be called with the `value` and the already deserialized\n`key` (i.e. `(value: string, key: PropertyKey) =\u003e *`).\n\nFor example:\n\n```ts\nparse('foo=300', {\n  valueDeserializer: (value) =\u003e {\n    const asNum = Number(value);\n    return Number.isNaN(asNum) ? value : asNum;\n  }\n});\n\n// {foo: 300}\n```\n\n### `keyDeserializer`\n\nCan be set to a function which will be used to deserialize each key during\nparsing.\n\nIt will be called with the `key` from the query string\n(i.e. `(key) =\u003e PropertyKey`).\n\nFor example:\n\n```ts\nparse('300=foo', {\n  keyDeserializer: (key) =\u003e {\n    const asNum = Number(key);\n    return Number.isNaN(asNum) ? key : asNum;\n  }\n});\n\n// {300: 'foo'}\n```\n\n### `shouldSerializeObject`\n\nCan be set to a function which determines if an _object-like_ value should be\nserialized instead of being treated as a nested object.\n\n**All non-object primitives will always be serialized.**\n\nFor example:\n\n```\n// Assuming `StringifableObject` returns its constructor value when `toString`\n// is called.\nstringify({\n  foo: new StringifiableObject('test')\n}, {\n  shouldSerializeObject(val) {\n    return val instanceof StringifableObject;\n  },\n  valueSerializer: (value) =\u003e {\n    return String(value);\n  }\n});\n\n// foo=test\n```\n\nIf you want to fall back to the default logic, you can import the default\nfunction:\n\n```\nimport {defaultShouldSerializeObject, stringify} from 'picoquery';\n\nstringify({\n  foo: new StringifiableObject('test')\n}, {\n  shouldSerializeObject(val) {\n    if (val instanceof StringifableObject) {\n      return true;\n    }\n    return defaultShouldSerializeObject(val);\n  }\n});\n```\n\n### `valueSerializer`\n\nCan be set to a function which will be used to serialize each value during\nstringifying.\n\nIt will be called with the `value` and the `key`\n(i.e. `(value: unknown, key: PropertyKey) =\u003e string`).\n\nFor example:\n\n```ts\nstringify({foo: 'bar'}, {\n  valueSerializer: (val) =\u003e String(val) + String(val)\n});\n\n// foo=barbar\n```\n\n**Note** that you can import the default serializer if you only want to handle\nsome cases.\n\nFor example:\n\n```ts\nimport {defaultValueSerializer, stringify} from 'picoquery';\n\nstringify({foo: 'bar'}, {\n  valueSerializer: (val, key) =\u003e {\n    if (val instanceof Date) {\n      return val.toISOString();\n    }\n\n    // Call the original serializer otherwise\n    return defaultValueSerializer(val, key);\n  }\n});\n```\n\n## Benchmarks\n\n**IMPORTANT**: there are a few things to take into account with these\nbenchmarks:\n\n- `fast-querystring` is not capable of parsing or stringifying nested objects,\nso the results are incomparible (but here as reference)\n- all libraries have their own level of configurability. It will be possible\nto increase perf in each of them by disabling various features, but these are\njust the 'happy path'\n\n### Parse\n\n```\nBenchmark: Basic (no nesting)\n┌─────────┬─────────────────────────────────┬─────────────┬────────────────────┬──────────┬─────────┐\n│ (index) │ Task Name                       │ ops/sec     │ Average Time (ns)  │ Margin   │ Samples │\n├─────────┼─────────────────────────────────┼─────────────┼────────────────────┼──────────┼─────────┤\n│ 0       │ 'picoquery'                     │ '2,393,539' │ 417.79130492907393 │ '±0.42%' │ 1196770 │\n│ 1       │ 'qs'                            │ '382,933'   │ 2611.4212945313157 │ '±1.04%' │ 191467  │\n│ 2       │ 'fast-querystring (no nesting)' │ '2,633,148' │ 379.77342802356833 │ '±1.58%' │ 1316575 │\n└─────────┴─────────────────────────────────┴─────────────┴────────────────────┴──────────┴─────────┘\nBenchmark: Dot-syntax nesting\n┌─────────┬─────────────────────────────────┬─────────────┬───────────────────┬──────────┬─────────┐\n│ (index) │ Task Name                       │ ops/sec     │ Average Time (ns) │ Margin   │ Samples │\n├─────────┼─────────────────────────────────┼─────────────┼───────────────────┼──────────┼─────────┤\n│ 0       │ 'picoquery'                     │ '1,406,039' │ 711.2176054736389 │ '±0.56%' │ 703020  │\n│ 1       │ 'qs'                            │ '205,611'   │ 4863.536155478235 │ '±0.98%' │ 102806  │\n│ 2       │ 'fast-querystring (no nesting)' │ '2,588,560' │ 386.3151031345139 │ '±0.66%' │ 1294281 │\n└─────────┴─────────────────────────────────┴─────────────┴───────────────────┴──────────┴─────────┘\n```\n\n### Stringify\n\n```\nBenchmark: Basic (no nesting)\n┌─────────┬─────────────────────────────────┬─────────────┬────────────────────┬──────────┬─────────┐\n│ (index) │ Task Name                       │ ops/sec     │ Average Time (ns)  │ Margin   │ Samples │\n├─────────┼─────────────────────────────────┼─────────────┼────────────────────┼──────────┼─────────┤\n│ 0       │ 'picoquery'                     │ '4,163,092' │ 240.20605684139227 │ '±0.16%' │ 2081547 │\n│ 1       │ 'qs'                            │ '843,630'   │ 1185.352608720127  │ '±0.76%' │ 421816  │\n│ 2       │ 'fast-querystring (no nesting)' │ '3,795,565' │ 263.46536774751036 │ '±0.24%' │ 1897783 │\n└─────────┴─────────────────────────────────┴─────────────┴────────────────────┴──────────┴─────────┘\nBenchmark: Dot-syntax nesting\n┌─────────┬─────────────────────────────────┬─────────────┬────────────────────┬──────────┬─────────┐\n│ (index) │ Task Name                       │ ops/sec     │ Average Time (ns)  │ Margin   │ Samples │\n├─────────┼─────────────────────────────────┼─────────────┼────────────────────┼──────────┼─────────┤\n│ 0       │ 'picoquery'                     │ '1,768,770' │ 565.3644818387182  │ '±1.08%' │ 884387  │\n│ 1       │ 'qs'                            │ '332,254'   │ 3009.743667534287  │ '±1.38%' │ 166128  │\n│ 2       │ 'fast-querystring (no nesting)' │ '7,227,031' │ 138.36940410118828 │ '±1.15%' │ 3613517 │\n└─────────┴─────────────────────────────────┴─────────────┴────────────────────┴──────────┴─────────┘\n```\n\n## License\n\nMIT\n","funding_links":["https://github.com/sponsors/43081j"],"categories":["Utilities","TypeScript"],"sub_categories":["HTTP / URLs"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F43081j%2Fpicoquery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F43081j%2Fpicoquery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F43081j%2Fpicoquery/lists"}