{"id":21736377,"url":"https://github.com/kyza/worst-json-stringify","last_synced_at":"2025-08-16T13:43:18.408Z","repository":{"id":40569661,"uuid":"507657298","full_name":"Kyza/worst-json-stringify","owner":"Kyza","description":"Extremely fast JSON stringifying *almost* without iteration.","archived":false,"fork":false,"pushed_at":"2022-10-27T01:17:47.000Z","size":271,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-13T01:54:54.785Z","etag":null,"topics":["fast-json-stringify","json","protobuf","schema","slow-json-stringify","stringify"],"latest_commit_sha":null,"homepage":"","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/Kyza.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-26T18:45:51.000Z","updated_at":"2024-11-20T17:53:48.000Z","dependencies_parsed_at":"2023-01-19T22:18:03.353Z","dependency_job_id":null,"html_url":"https://github.com/Kyza/worst-json-stringify","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fworst-json-stringify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fworst-json-stringify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fworst-json-stringify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fworst-json-stringify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kyza","download_url":"https://codeload.github.com/Kyza/worst-json-stringify/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654051,"owners_count":21140235,"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":["fast-json-stringify","json","protobuf","schema","slow-json-stringify","stringify"],"created_at":"2024-11-26T05:18:31.553Z","updated_at":"2025-04-13T01:55:19.270Z","avatar_url":"https://github.com/Kyza.png","language":"TypeScript","readme":"# worst-json-stringify\r\n\r\nExtremely fast JSON stringifying *almost* without iteration.\r\n\r\n## Usage\r\n\r\n```bash\r\npnpm i worst-json-stringify\r\n```\r\n\r\n```js\r\nconst stringifyUser = makeStringifier({\r\n\ttype: \"struct\",\r\n\tchildren: {\r\n\t\tfirstName: { type: \"string\" },\r\n\t\tlastName: { type: \"string\", optional: true },\r\n\t\tage: { type: \"number\" },\r\n\t\tobj: {\r\n\t\t\ttype: \"object\",\r\n\t\t\ttypes: [{ type: \"number\" }, { type: \"boolean\" }],\r\n\t\t},\r\n\t},\r\n});\r\n\r\nconsole.log(\"Function Source:\", stringifyUser.toString());\r\n\r\nconsole.log(\r\n\t\"User String:\",\r\n\tstringifyUser({\r\n\t\tfirstName: \"John\\u1782\",\r\n\t\tage: Infinity,\r\n\t\tobj: {\r\n\t\t\tone: true,\r\n\t\t\ttwo: NaN,\r\n\t\t},\r\n\t})\r\n);\r\n```\r\n\r\n## Benchmarks\r\n\r\n### Fastest Possible Options\r\n\r\n```bash\r\ncpu: Intel(R) Core(TM) i7-8086K CPU @ 4.00GHz\r\nruntime: node v17.0.1 (x64-win32)\r\n\r\nbenchmark                 time (avg)             (min … max)       p75       p99      p995\r\n------------------------------------------------------------ -----------------------------\r\n• large string\r\n------------------------------------------------------------ -----------------------------\r\nnative                 24.44 µs/iter    (20.8 µs … 610.8 µs)   22.4 µs   59.3 µs  102.2 µs\r\nfast-json-stringify    23.89 µs/iter     (19.4 µs … 2.08 ms)   21.4 µs   61.5 µs    120 µs\r\nslow-json-stringify     1.62 µs/iter     (1.38 µs … 3.01 µs)   1.68 µs   3.01 µs   3.01 µs\r\nworst-json-stringify  702.44 ns/iter   (636.18 ns … 1.29 µs) 709.02 ns   1.29 µs   1.29 µs\r\nprotobuf               10.52 µs/iter      (4.2 µs … 4.76 ms)    8.5 µs   58.6 µs   81.5 µs\r\n\r\nsummary for large string\r\n  worst-json-stringify\r\n   2.31x faster than slow-json-stringify\r\n   14.98x faster than protobuf\r\n   34x faster than fast-json-stringify\r\n   34.79x faster than native\r\n```\r\n\r\n### Safest Possible Options\r\n\r\n```bash\r\ncpu: Intel(R) Core(TM) i7-8086K CPU @ 4.00GHz\r\nruntime: node v17.0.1 (x64-win32)\r\n\r\nbenchmark                 time (avg)             (min … max)       p75       p99      p995\r\n------------------------------------------------------------ -----------------------------\r\n• large string\r\n------------------------------------------------------------ -----------------------------\r\nnative                 23.12 µs/iter    (20.8 µs … 237.2 µs)   21.9 µs   41.6 µs   74.7 µs\r\nfast-json-stringify    21.89 µs/iter      (19.3 µs … 766 µs)   20.6 µs   40.3 µs     81 µs\r\nslow-json-stringify     7.39 µs/iter    (6.42 µs … 10.18 µs)   7.84 µs  10.18 µs  10.18 µs\r\nworst-json-stringify    5.12 µs/iter      (4.8 µs … 6.73 µs)   5.06 µs   6.73 µs   6.73 µs\r\nprotobuf               10.17 µs/iter      (4.2 µs … 3.53 ms)    8.8 µs   54.2 µs   76.1 µs\r\n\r\nsummary for large string\r\n  worst-json-stringify\r\n   1.44x faster than slow-json-stringify\r\n   1.99x faster than protobuf\r\n   4.28x faster than fast-json-stringify\r\n   4.52x faster than native\r\n```\r\n\r\n## Explaination\r\n\r\nThink of it like a macro. It takes in a schema and returns a function that is specifically made to stringify objects that match that schema. The function it generates--assuming it doesn't contain an `object` or `array` type--will stringify the object without iterating over any properties. That makes it incredibly fast at what it does.\r\n\r\n## Types\r\n\r\nCurrently the following types are supported:\r\n\r\n- [x] struct\r\n- [x] object\r\n- [x] tuple\r\n- [x] array\r\n- [x] string\r\n- [x] boolean\r\n- [x] number\r\n\r\n`struct`, and `tuple` have children. The direct children of a `tuple` can't be optional while the children of a `struct` can.\r\n\r\n`object` and `array` don't have children, they have a set of types that can be in them. If there are no types specified, it can be any type. The fewer types that are specified--excluding zero of course--the faster it is to stringify.\r\n\r\n`object` and `array` are the only types that can't be stringified without iterating. This is because of the nature of them having unknown lengths. That's why the `struct` and `tuple` types exist.\r\n\r\n## Options\r\n\r\nBy default, the stringifier will escape all strings. This will reduce performance drastically, but it's much safer, especially if you're using large strings. If you are *absolutely sure* you don't need to escape strings, you can pass `escape: false` to the `string` type on the schema.\r\n\r\nJSON does not support `Infinity` and `NaN` from IEEE 754, so by default the stringifier will convert `Infinity` and `NaN` to `null`. This will reduce performance slightly and lose data, but the result will be compatible with the specification and `JSON.parse`. To allow `Infinity` and `NaN` to be stringified \"properly\" you will need to use custom a replacer.\r\n\r\n```js\r\nconst stringifyUser = makeStringifier(\r\n\t{\r\n\t\ttype: \"tuple\",\r\n\t\tchildren: [\r\n\t\t\t{ type: \"number\" },\r\n\t\t\t{ type: \"number\", ieee754: true },\r\n\t\t\t{ type: \"bigint\" },\r\n\t\t\t{ type: \"regex\" },\r\n\t\t],\r\n\t},\r\n\t{\r\n\t\treplacer: (accessor, type, path, iterator) =\u003e {\r\n\t\t\t// Add BigInt support.\r\n\t\t\tif (!iterator \u0026\u0026 type.type === \"bigint\") {\r\n\t\t\t\treturn `${accessor}+\"n\"`;\r\n\t\t\t}\r\n\t\t\t// Add Infinity and NaN support.\r\n\t\t\tif (!iterator \u0026\u0026 type.type === \"number\" \u0026\u0026 type.ieee754) {\r\n\t\t\t\treturn accessor;\r\n\t\t\t}\r\n\t\t\t// Add RegExp support.\r\n\t\t\tif (type.type === \"regex\") {\r\n\t\t\t\tif (iterator) {\r\n\t\t\t\t\treturn `if(${accessor} instanceof RegExp)`;\r\n\t\t\t\t} else {\r\n\t\t\t\t\treturn `${accessor}.toString()`;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t}\r\n);\r\n\r\nconsole.log(stringifyUser.toString());\r\nconsole.log(stringifyUser([Infinity, NaN, 2n, /a/g]));\r\n```\r\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkyza%2Fworst-json-stringify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkyza%2Fworst-json-stringify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkyza%2Fworst-json-stringify/lists"}