{"id":13652854,"url":"https://github.com/xtao-org/jsonhilo","last_synced_at":"2025-04-07T12:06:52.647Z","repository":{"id":43766426,"uuid":"378699055","full_name":"xtao-org/jsonhilo","owner":"xtao-org","description":"Fast lossless JSON parse event streaming, in JavaScript.","archived":false,"fork":false,"pushed_at":"2025-02-24T23:15:31.000Z","size":325,"stargazers_count":39,"open_issues_count":3,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T10:08:01.960Z","etag":null,"topics":["deno","fast","high-level","high-performance","javascript","json","jsonhilo","large-language-models","lossless","low-level","minimal","modular","parser","runtime-independent","sax","sax-parser","streaming","ultra-fast","zero-dependency"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/xtao-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":{"ko_fi":"djedr","custom":["https://buycoffee.to/jevko","https://donate.stripe.com/00gdUicLv4UueeQcMM"]}},"created_at":"2021-06-20T17:07:08.000Z","updated_at":"2025-02-19T22:14:50.000Z","dependencies_parsed_at":"2023-12-08T15:24:52.092Z","dependency_job_id":"a65cfa0b-1e80-4f59-857e-baef688b309c","html_url":"https://github.com/xtao-org/jsonhilo","commit_stats":{"total_commits":46,"total_committers":4,"mean_commits":11.5,"dds":0.5,"last_synced_commit":"596814636eda694739c2d76e97928501a5742854"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtao-org%2Fjsonhilo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtao-org%2Fjsonhilo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtao-org%2Fjsonhilo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtao-org%2Fjsonhilo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xtao-org","download_url":"https://codeload.github.com/xtao-org/jsonhilo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247648977,"owners_count":20972945,"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":["deno","fast","high-level","high-performance","javascript","json","jsonhilo","large-language-models","lossless","low-level","minimal","modular","parser","runtime-independent","sax","sax-parser","streaming","ultra-fast","zero-dependency"],"created_at":"2024-08-02T02:01:03.389Z","updated_at":"2025-04-07T12:06:52.622Z","avatar_url":"https://github.com/xtao-org.png","language":"JavaScript","readme":"\u003cimg src=\"logo.png\" alt=\"logo\" height=\"128\" /\u003e\n\n# JsonHilo.js\n\n[![blog post](https://img.shields.io/badge/📢%20blog%20post-darkgreen?style=flat-square)](https://djedr.github.io/posts/jsonhilo-2021-07-29.html) [![npm downloads](https://shields.io/npm/dm/@xtao-org/jsonhilo?style=flat-square\u0026logo=npm\u0026labelColor=darkred\u0026color=grey)](https://www.npmjs.com/package/@xtao-org/jsonhilo) [![jsDelivr hits](https://img.shields.io/jsdelivr/gh/hm/xtao-org/jsonhilo?style=flat-square\u0026logo=jsdelivr\u0026logoColor=white\u0026label=jsDelivr%20hits\u0026labelColor=%23ff5627\u0026color=grey)](https://www.jsdelivr.com/package/gh/xtao-org/jsonhilo)\n\nMinimal [lossless](#lossless) JSON parse event streaming, akin to [SAX](https://en.wikipedia.org/wiki/Simple_API_for_XML).\n\n***\n\nHandcrafted by \u003ca href=\"https://djedr.github.io\"\u003eDarius J Chuck\u003c/a\u003e.\n\n\u003ca href=\"https://donate.stripe.com/00gdUicLv4UueeQcMM\" target=\"_blank\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/djedr/djedr.github.io/master/gfx/donate-but.svg\" style=\"height: 32px\" alt=\"Donate directly via Stripe\" title=\"Donate directly via Stripe\"\u003e\u003c/a\u003e\n\u0026nbsp;\nor\n\u0026nbsp;\n\u003ca href='https://ko-fi.com/djedr' target='_blank'\u003e\u003cimg width=\"120\" style='border:0px;width:120px;' src='https://storage.ko-fi.com/cdn/kofi1.png?v=3' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n\u0026nbsp;\n\u003ca href=\"https://buycoffee.to/jevko\" target=\"_blank\"\u003e\u003cimg width=\"120\" src=\"https://buycoffee.to/btn/buycoffeeto-btn-primary.svg\" style=\"width: 120px\" alt=\"Postaw mi kawę na buycoffee.to\"\u003e\u003c/a\u003e\n\n***\n\n[Fast](#fast), [modular](#modular), and dependency-free. \n\nProvides two interfaces: a [**hi**gh-level](#jsonhigh) one and a [**lo**w-level](#jsonlow) one.\n\nWritten in [runtime-independent](#runtime-independent) JavaScript. \n\nWorks in [Deno](https://deno.land/), [Node.js](https://nodejs.org), and the browser.\n\n## Status\n\nStable.\n\n[Passes standards-compliance tests](#standards-compliant) and [performs well in benchmarks](#fast).\n\nBattle-tested.\n\n## Installation\n\n### Node.js\n\nAn [npm package](https://www.npmjs.com/package/@xtao-org/jsonhilo) is available:\n\n```\nnpm i @xtao-org/jsonhilo\n```\n\n### Deno and the browser\n\nImport modules directly from [deno.land/x](https://deno.land/x):\n\n```js\nimport {JsonHigh} from 'https://deno.land/x/jsonhilo@v0.4.1/mod.js'\n```\n\nOr from a CDN such as [jsDelivr](https://www.jsdelivr.com/):\n\n```js\nimport {JsonHigh} from 'https://cdn.jsdelivr.net/gh/xtao-org/jsonhilo@v0.4.1/mod.js'\n```\n\n\u003c!-- An easy alternative that will work for all environments is to copy and use [`jsonhilo.bundle.js`](jsonhilo.bundle.js), e.g.:\n\n```\ncurl https://raw.githubusercontent.com/tree-annotation/json-stream-js/jsonhilo.bundle.js \u003e jsonhilo.bundle.js\n```\n\nand then:\n\n```js\nimport {JsonHigh} from 'jsonhilo.bundle.js'\n```\n\nThe bundle was obtained with [`deno bundle`](https://deno.land/manual/tools/bundler) and exports the same modules as [`mod.js`](mod.js), all dependencies included. --\u003e\n\n## Quickstart\n\nSee a basic example in [`demo/basic.js`](demo/basic.js), pasted below:\n\n```js\nimport {JsonHigh} from '@xtao-org/jsonhilo'\nconst stream = JsonHigh({\n  openArray: () =\u003e console.log('\u003carray\u003e'),\n  openObject: () =\u003e console.log('\u003cobject\u003e'),\n  closeArray: () =\u003e console.log('\u003c/array\u003e'),\n  closeObject: () =\u003e console.log('\u003c/object\u003e'),\n  key: (key) =\u003e console.log(`\u003ckey\u003e${key}\u003c/key\u003e`),\n  value: (value) =\u003e console.log(`\u003cvalue type=\"${typeof value}\"\u003e${value}\u003c/value\u003e`),\n})\nstream.chunk('{\"tuple\": [null, true, false, 1.2e-3, \"[demo]\"]}')\n```\n\nThis uses [the simplified high-level interface](#jsonhigh) built on top of the [more powerful low-level core](#jsonlow).\n\n## Features\n\n* Simple and minimal\n* Dependency-free\n* [Runtime-independent](#runtime-independent)\n* [Lossless](#lossless)\n* [Modular](#modular)\n* [Fast](#fast)\n* [Streaming-friendly](#streaming-friendly)\n* [Optionally standards-compliant](#standards-compliant)\n* [Unicode-compatible](#unicode-compatible)\n\n## Runtime-independent\n\nThe library logic is written in modern JavaScript and relies upon some of its features, standard modules in particular.\n\nBeyond that it does not use any runtime-specific features and should work in any *modern* JavaScript environment. It was tested in Deno, Node.js, and the browser.\n\nThat said, the primary target runtime is Deno, and tests depend on it.\n\n## Lossless\n\nUnlike any other known streaming JSON parser, JsonHilo provides a [low-level](#jsonlow) interface for *lossless* parsing, i.e. it is possible to recover the *exact* input, including whitespace and string escape sequences, from parser events.\n\nThis feature can be used to implement accurate translators from JSON to other representations (see [Rationale](#rationale)), syntax highlighters (demo below), JSON scanners that search for substrings in strings on-the-fly, without first loading them into memory, and more.\n\n\u003cimg src=\"highlight.gif\" alt=\"Highlight demo\" height=\"320\" /\u003e\n\nPictured above is the syntax highlighting demo: [demo/highlight.js](demo/highlight.js)\n\n## Modular\n\nThe library is highly modular with [a fully independent core](#jsonlow), around which various adapters and extensions are built, including [an easy-to-use high-level interface](#jsonhigh).\n\n## JsonLow\n\nThe core module is [**`JsonLow.js`**](JsonLow.js). It has no dependencies, so it can be used on its own. It is very minimal and optimized for maximum performance and accuracy, as well as minimum memory footprint. It provides the most fine-grained control over the parsing process. The events generated by the parser carry enough information to losslessly recreate the input exactly, including whitespace.\n\nSee [**JsonLow.d.ts**](JsonLow.d.ts) for type information and [demo/highlight.js](demo/highlight.js) for usage example.\n\n\u003c!-- *Detailed description to be written.* --\u003e\n\n## JsonHigh\n\n[**`JsonHigh.js`**](JsonHigh.js) is the high-level module which provides a more convenient interface. It is composed of auxiliary modules and adapters built around the core. It is optimized for convenience and provides similar functionality and granularity to other streaming parsers, such as [Clarinet](https://github.com/dscape/clarinet) or [creationix/jsonparse](https://github.com/creationix/jsonparse).\n\nSee [**JsonHigh.d.ts**](JsonHigh.d.ts) for type information and [Quickstart](#quickstart) for usage example.\n\n### Parameters\n\n`JsonHigh` is called with an object which contains named event handlers that are invoked during parsing. All handlers and are optional and described [below](#basic-events).\n\nThe object may also contain [options](#options) to change the default behavior, e.g. [turn off number parsing](#parseNumbers) or turn on [buffering of strings piece-by-piece](#maxStringBufferLength).\n\n### Return value\n\n`JsonHigh` returns a stream object with the following methods:\n\n\u003ca id=\"chunk-stream-method\"\u003e\u003c/a\u003e\n\n* #### `chunk(c: string)` \n\n  Accepts a JSON chunk to parse. \n\n  Returns the stream object for chaining. \n\n\u003ca id=\"end-stream-method\"\u003e\u003c/a\u003e\n\n* #### `end()`\n\n  Call it to signal to the stream that the current JSON document is finished.\n  \n  If there is no error, it will then call the corresponding [`end()` event handler](#end-event-handler), and return whatever that returned.\n\n* #### `depth()`\n\n  Returns current depth (level of nesting). \n  \n  **NOTE**: an `open*` or `close*` handler is always called *after* the depth is updated, meaning:\n\n  * In `openObject`/`openArray` handlers the lowest depth reported will be 1 -- we entered a top-level object/array and are now at depth 1.\n  \n  * In `closeObject`/`closeArray` handlers the lowest depth reported will be 0 -- we exited a top-level object/array and are now at depth 0 (top-level).\n\n### Basic events\n\nThe basic usage of `JsonHigh` involves 4 event handlers without arguments which indicate start and end of structures:\n\n* #### `openArray()`\n\n  An array started (`[`).\n\n* #### `closeArray()`\n  \n  An array ended (`]`).\n\n* #### `openObject()`\n\n  An object started (`{`).\n\n* #### `closeObject()`\n\n  An object ended (`}`)\n\nAnd 2 event handlers with one argument which capture primitives:\n\n* #### `key(k: string)`\n  \n  An object's key ended. \n  \n  The argument of the handler contains the key as a JavaScript string. \n  \n  This event can be suppressed by setting [`maxStringBufferLength`](#maxStringBufferLength).\n\n* #### `value(v: true | false | null | number | string)`\n\n  A primitive JSON value ended. \n  \n  The argument of the event contains the corresponding JavaScript value: `true`, `false`, `null`, a number, or a string. \n\n  This event can be suppressed for numbers if [`parseNumbers`](#parseNumbers) is set to `false` and for strings if [`maxStringBufferLength`](#maxStringBufferLength) is set.\n\nFinally, there is:\n\n\u003ca id=\"end-event-handler\"\u003e\u003c/a\u003e\n\n* #### `end()`\n\n  An argumentless event handler which is called by the [`end()` method of the stream](#end-stream-method) to confirm that the parsed JSON document is complete and valid.\n\nNote that an event handler won't be called if there is an error in the parsed JSON, see [error handling](#error-handling).\n\n\u003c!-- ?todo: move non-basic options to a separate doc --\u003e\n### Extra events\n\nThese handlers take no arguments.\n\n* #### `openKey()`\n\n  A key started (`\"`, in key position).\n\n* #### `openString()`\n\n  A string value started (`\"`).\n\n* #### `openNumber()` \n\n  A number value started.\n\n### Conditional events\n\nThe following handlers take no arguments.\n\n* #### `closeKey()`\n\n  A key ended (`\"`).\n  \n  Called instead of the `key` event **when `maxStringBufferLength` is set**.\n\n* #### `closeString()`\n\n  A string value ended (`\"`).\n  \n  Called instead of the `value` event **when `maxStringBufferLength` is set**.\n\nThe following handlers receive the buffer that should be consumed.\n\n* #### `bufferKey(buffer: string)`\n\n  Key buffer is ready for consumption\n  \n  Called instead of the `key` event **when `maxStringBufferLength` is set**.\n  \n  The buffer then contains `maxStringBufferLength` code points or possibly less if we reached the end of a key.\n\n* #### `bufferString(buffer: string)`\n\n  String buffer is ready for consumption.\n  \n  For string values, called instead of the `value` event **when `maxStringBufferLength` is set**.\n  \n  The buffer then contains `maxStringBufferLength` code points or possibly less if we reached the end of a string value.\n\n* #### `bufferNumber(buffer: string)`\n\n  Number buffer is ready for consumption.\n  \n  For number values, called instead of the `value` event **when `parseNumbers` is set**.\n  \n  The buffer then contains the unparsed number (represented as a string).\n\n### Options\n\n\u003ca id=\"maxStringBufferLength\"\u003e\u003c/a\u003e\n\n* #### `maxStringBufferLength: number = Infinity`\n\n  The maximum length of the key or string buffer, in code points.\n\n  If set, the `key` event handler won't be called and, for strings, the `value` event handler won't be called. \n\n  Instead, the `bufferKey` and `bufferString` handlers will be called as soon as the given number of code points has been collected or when the key/string is finished. \n\n  In the latter case the number of code points may be smaller than `maxStringBufferLength` and a `closeKey`/`closeString` handler will be called after the last `*Buffer` event to signal the finish. \n\n  This is useful when dealing with long strings where it's desirable to stream them piece-by-piece, e.g. when working with LLMs (Large Language Models). \n\n  See [Add support for incomplete key and value strings #10](https://github.com/xtao-org/jsonhilo/issues/10) for more information.\n\n\u003ca id=\"parseNumbers\"\u003e\u003c/a\u003e\n\n* #### `parseNumbers: boolean = true`\n\n  Controls whether numbers should be parsed (converted to JavaScript `number` type) which is the case by default.\n\n  If set to `false`, the `value` event handler won't be called for numbers. Instead, the `bufferNumber` handler will be called with the number as a string.\n\n  This is useful when dealing with big numbers which would lose precision when converted to the `number` type.\n\n\u003ca id=\"maxNumberLength\"\u003e\u003c/a\u003e\n\n* #### `maxNumberLength: number = 8192`\n\n  Specifies the maximum length of a number value (in characters).\n\n### Error handling\n\nIf there is an error when [parsing a `chunk()`](#chunk-stream-method), an `Error` is thrown, containing a serialized JSON object with details such as the error message.\n\nIf there is an error [at the `end()`](#end-stream-method), that error is returned to the caller. The user-provided [`end()` event handler](#end-event-handler) is not called, so it should not contain any [cleanup](#cleanup) code.\n\n### Cleanup\n\nTo run cleanup code at the end of parsing a document regardless of whether there was an error or not, **don't put that code in the end handler**. Instead put it after `.end()`, like so:\n\n```js\n// ...\nstream.end()\ncleanup()\n```\n\nIf you want to also handle an error, you can use the `isError` helper:\n\n```js\nimport {isError} from '@xtao-org/jsonhilo'\n\n// ...\n\nconst ret = stream.end()\nif (isError(ret)) { handle(ret) } // handle error\ncleanup()\n```\n\nIf your error handler can throw, you can use `try-catch-finally`:\n\n```js\nimport {isError} from '@xtao-org/jsonhilo'\n\n// ...\n\nconst ret = stream.end()\ntry { if (isError(ret)) { handle(ret) } }\ncatch (e) { /* optional */ }\nfinally { cleanup() }\n```\n\n## Fast\n\nAchieving optimal performance without sacrificing simplicity and correctness was a design goal of JsonHilo. This goal was realized and for applications without extreme performance requirements JsonHilo should be more than fast enough.\n\nIt may be worth noting however that using pure JavaScript for extremely performance-sensitive applications is ill-advised and that nothing can replace individual case-by-case benchmarks.\n\nIt is difficult to find a parser that can be sensibly compared with JsonHilo. The one that comes the closest and is fairly widely known is [Clarinet](https://github.com/dscape/clarinet). It is the only low-level streaming JSON parser featured on [JSON.org](https://www.json.org) and the fastest one I could find.\n\n[xtao-org/jsonhilo-benchmarks](https://github.com/xtao-org/jsonhilo-benchmarks) contains simple benchmarks used to compare the performance of JsonHilo with Clarinet and [jq](https://stedolan.github.io/jq/) (a fast and versatile command-line JSON processor).\n\nAccording to these benchmarks, for validating JSON (just parsing without any further processing) JsonHilo is the fastest, before jq, which is in turn faster than Clarinet. Overall for comparable tasks the low-level JsonHilo interface is up to 2x faster than Clarinet, whereas the high-level interface is on par.\n\nAgain, these results need to be taken with a grain of salt, and there is no replacement for individual benchmarks. Use whatever suits your case best. In most cases, relative performance should not be the only factor to take into account.\n\nFactors which make a fair comparison between JsonHilo and Clarinet problematic are mentioned below.\n\n### Differences between JsonHilo and Clarinet\n\nThe major differences that make the comparison of the two problematic are:\n\n* [Clarinet is not fully ECMA-404-compliant](https://github.com/dscape/clarinet/issues/49), as measured by [JSON Parsing Test Suite by Nicolas Seriot](https://github.com/nst/JSONTestSuite) -- it accepts certain invalid JSON and rejects certain valid JSON. JsonHilo is designed to parse the JSON grammar correctly and so [can pass the ECMA-404-compliance test suite](#standards-compliant). JsonHilo is overall safer to use with unknown inputs -- it can very well be used as a validator.\n* JsonHilo fundamentally operates on individual Unicode code points as opposed to strings, chunks, or characters. Performance-wise this may be an advantage or a disadvantage, depending on how the input is structured (it may need conversion). \n* Even though low-level processing with JsonHilo may be overall significantly faster than Clarinet, the fact that the former does not use regular expressions to parse the input while the latter does may lead to a narrower performance gap between the two.\n* JsonHilo is overall simpler in terms of code complexity, making it easier to adjust or audit. The code is also significantly smaller in size than Clarinet, even taking into account the optional high-level interfaces laid on top of the tiny core.\n* JsonHilo's core is more low-level and amenable to extension.\n\n## Streaming-friendly\n\nBy default the parser is streaming-friendly by accepting the following:\n\n* Multiple consecutive top-level JSON values -- it can read [line-delimited JSON and concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming), e.g. [JSON Lines](https://jsonlines.org/)/JSONL, [NDJSON](https://web.archive.org/web/20231218162511/https://ndjson.org/). Whitespace-separated primitives are also supported.\n\n* [Trailing commas](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas) -- a single trailing comma in an array or an object generates no errors.\n\n* Zero-length or whitespace-only input -- generates no errors.\n\n## Standards-compliant\n\nThe [streaming-friendly features](#streaming-friendly) can be supressed by [**`Ecma404.js`**](Ecma404.js), an adapter module which provides full [ECMA-404](https://www.ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf)/[RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) compliance.\n\nThis is confirmed by passing the [JSON Parsing Test Suite](https://github.com/nst/JSONTestSuite) by [Nicolas Seriot](https://github.com/nst), available under `test/JSONTestSuite`.\n\nTests can be run with Deno as follows:\n\n```\ndeno test --allow-read\n```\n\n## Unicode-compatible\n\nThe [core logic](#jsonlow) operates on Unicode code points -- in line with spec -- rather than code units or characters.\n\n## Rationale\n\nInitially written to enable fast lossless translation between JSON and [Jevko](https://jevko.org), as no suitable JSON parser in JavaScript exists.\n\nI decided to release this as a separate library, because I was tinkering with Deno and found that there was [no streaming JSON parser available at all for Deno](https://stackoverflow.com/questions/58070346/reading-large-json-file-in-deno).\n\n## See also\n\n[JsonStrum](https://github.com/xtao-org/jsonstrum) -- a high-level wrapper over JsonHilo which emits fully parsed objects and arrays.\n\n## License\n\nReleased under the [MIT](LICENSE) license.\n\n## Support this project\n\n\u003cp\u003eI prefer to share my creations for free. However living and creating without money is not possible for me. So I ask companies and people, who want and can, for support. Every symbolic cup of coffee counts!\u003c/p\u003e\n\n\u003cdiv class=\"flexi\" style=\"flex-wrap: wrap;\"\u003e\n  \u003ca href=\"https://donate.stripe.com/00gdUicLv4UueeQcMM\" target=\"_blank\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/djedr/djedr.github.io/master/gfx/donate-but.svg\" style=\"height: 64px\" alt=\"Donate directly via Stripe\" title=\"Donate directly via Stripe\"\u003e\u003c/a\u003e\n  \u0026nbsp;\n  or\n  \u0026nbsp;\n  \u003ca href='https://ko-fi.com/djedr' target='_blank'\u003e\u003cimg width='240' style='border:0px;width:240px;' src='https://storage.ko-fi.com/cdn/kofi1.png?v=3' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://buycoffee.to/jevko\" target=\"_blank\"\u003e\u003cimg width='240' src=\"https://buycoffee.to/btn/buycoffeeto-btn-primary.svg\" style=\"width: 240px\" alt=\"Postaw mi kawę na buycoffee.to\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n## Paid support and online assistance\n\nIf you prefer, [you can get paid help and support, including direct online assistance, related to JsonHilo.js through Githelp.](https://githelp.app/repos/jsonhilo)\n\nAt the moment this is a limited opportunity to try an early version of Githelp.\n\n***\n\n\u003cimg src=\"tao-json.png\" alt=\"tao-json-logo\" height=\"128\" /\u003e\n\nA stand-alone part of the [TAO](https://xtao.org)-JSON project.\n\n© 2021-2025 [xtao.org](https://xtao.org)","funding_links":["https://ko-fi.com/djedr","https://buycoffee.to/jevko","https://donate.stripe.com/00gdUicLv4UueeQcMM","https://ko-fi.com/djedr'"],"categories":["Libraries"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtao-org%2Fjsonhilo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxtao-org%2Fjsonhilo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtao-org%2Fjsonhilo/lists"}