source: imaps-frontend/node_modules/@discoveryjs/json-ext/README.md

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[79a0317]1# json-ext
2
3[![NPM version](https://img.shields.io/npm/v/@discoveryjs/json-ext.svg)](https://www.npmjs.com/package/@discoveryjs/json-ext)
4[![Build Status](https://github.com/discoveryjs/json-ext/actions/workflows/ci.yml/badge.svg)](https://github.com/discoveryjs/json-ext/actions/workflows/ci.yml)
5[![Coverage Status](https://coveralls.io/repos/github/discoveryjs/json-ext/badge.svg?branch=master)](https://coveralls.io/github/discoveryjs/json-ext)
6[![NPM Downloads](https://img.shields.io/npm/dm/@discoveryjs/json-ext.svg)](https://www.npmjs.com/package/@discoveryjs/json-ext)
7
8A set of utilities designed to extend JSON's capabilities, especially for handling large JSON data (over 100MB) efficiently:
9
10- [parseChunked()](#parsechunked) – Parses JSON incrementally; similar to [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse), but processing JSON data in chunks.
11- [stringifyChunked()](#stringifychunked) – Converts JavaScript objects to JSON incrementally; similar to [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), but returns a generator that yields JSON strings in parts.
12- [stringifyInfo()](#stringifyinfo) – Estimates the size of the `JSON.stringify()` result and identifies circular references without generating the JSON.
13- [parseFromWebStream()](#parsefromwebstream) – A helper function to parse JSON chunks directly from a Web Stream.
14- [createStringifyWebStream()](#createstringifywebstream) – A helper function to generate JSON data as a Web Stream.
15
16### Key Features
17
18- Optimized to handle large JSON data with minimal resource usage (see [benchmarks](./benchmarks/README.md))
19- Works seamlessly with browsers, Node.js, Deno, and Bun
20- Supports both Node.js and Web streams
21- Available in both ESM and CommonJS
22- TypeScript typings included
23- No external dependencies
24- Compact size: 9.4Kb (minified), 3.8Kb (min+gzip)
25
26### Why json-ext?
27
28- **Handles large JSON files**: Overcomes the limitations of V8 for strings larger than ~500MB, enabling the processing of huge JSON data.
29- **Prevents main thread blocking**: Distributes parsing and stringifying over time, ensuring the main thread remains responsive during heavy JSON operations.
30- **Reduces memory usage**: Traditional `JSON.parse()` and `JSON.stringify()` require loading entire data into memory, leading to high memory consumption and increased garbage collection pressure. `parseChunked()` and `stringifyChunked()` process data incrementally, optimizing memory usage.
31- **Size estimation**: `stringifyInfo()` allows estimating the size of resulting JSON before generating it, enabling better decision-making for JSON generation strategies.
32
33## Install
34
35```bash
36npm install @discoveryjs/json-ext
37```
38
39## API
40
41### parseChunked()
42
43Functions like [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse), iterating over chunks to reconstruct the result object, and returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
44
45> Note: `reviver` parameter is not supported yet.
46
47```ts
48function parseChunked(input: Iterable<Chunk> | AsyncIterable<Chunk>): Promise<any>;
49function parseChunked(input: () => (Iterable<Chunk> | AsyncIterable<Chunk>)): Promise<any>;
50
51type Chunk = string | Buffer | Uint8Array;
52```
53
54[Benchmark](https://github.com/discoveryjs/json-ext/tree/master/benchmarks#parse-chunked)
55
56Usage:
57
58```js
59import { parseChunked } from '@discoveryjs/json-ext';
60
61const data = await parseChunked(chunkEmitter);
62```
63
64Parameter `chunkEmitter` can be an iterable or async iterable that iterates over chunks, or a function returning such a value. A chunk can be a `string`, `Uint8Array`, or Node.js `Buffer`.
65
66Examples:
67
68- Generator:
69 ```js
70 parseChunked(function*() {
71 yield '{ "hello":';
72 yield Buffer.from(' "wor'); // Node.js only
73 yield new TextEncoder().encode('ld" }'); // returns Uint8Array
74 });
75 ```
76- Async generator:
77 ```js
78 parseChunked(async function*() {
79 for await (const chunk of someAsyncSource) {
80 yield chunk;
81 }
82 });
83 ```
84- Array:
85 ```js
86 parseChunked(['{ "hello":', ' "world"}'])
87 ```
88- Function returning iterable:
89 ```js
90 parseChunked(() => ['{ "hello":', ' "world"}'])
91 ```
92- Node.js [`Readable`](https://nodejs.org/dist/latest-v14.x/docs/api/stream.html#stream_readable_streams) stream:
93 ```js
94 import fs from 'node:fs';
95
96 parseChunked(fs.createReadStream('path/to/file.json'))
97 ```
98- Web stream (e.g., using [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)):
99 > Note: Iterability for Web streams was added later in the Web platform, not all environments support it. Consider using `parseFromWebStream()` for broader compatibility.
100 ```js
101 const response = await fetch('https://example.com/data.json');
102 const data = await parseChunked(response.body); // body is ReadableStream
103 ```
104
105### stringifyChunked()
106
107Functions like [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), but returns a generator yielding strings instead of a single string.
108
109> Note: Returns `"null"` when `JSON.stringify()` returns `undefined` (since a chunk cannot be `undefined`).
110
111```ts
112function stringifyChunked(value: any, replacer?: Replacer, space?: Space): Generator<string, void, unknown>;
113function stringifyChunked(value: any, options: StringifyOptions): Generator<string, void, unknown>;
114
115type Replacer =
116 | ((this: any, key: string, value: any) => any)
117 | (string | number)[]
118 | null;
119type Space = string | number | null;
120type StringifyOptions = {
121 replacer?: Replacer;
122 space?: Space;
123 highWaterMark?: number;
124};
125```
126
127[Benchmark](https://github.com/discoveryjs/json-ext/tree/master/benchmarks#stream-stringifying)
128
129Usage:
130
131- Getting an array of chunks:
132 ```js
133 const chunks = [...stringifyChunked(data)];
134 ```
135- Iterating over chunks:
136 ```js
137 for (const chunk of stringifyChunked(data)) {
138 console.log(chunk);
139 }
140 ```
141- Specifying the minimum size of a chunk with `highWaterMark` option:
142 ```js
143 const data = [1, "hello world", 42];
144
145 console.log([...stringifyChunked(data)]); // default 16kB
146 // ['[1,"hello world",42]']
147
148 console.log([...stringifyChunked(data, { highWaterMark: 16 })]);
149 // ['[1,"hello world"', ',42]']
150
151 console.log([...stringifyChunked(data, { highWaterMark: 1 })]);
152 // ['[1', ',"hello world"', ',42', ']']
153 ```
154- Streaming into a stream with a `Promise` (modern Node.js):
155 ```js
156 import { pipeline } from 'node:stream/promises';
157 import fs from 'node:fs';
158
159 await pipeline(
160 stringifyChunked(data),
161 fs.createWriteStream('path/to/file.json')
162 );
163 ```
164- Wrapping into a `Promise` streaming into a stream (legacy Node.js):
165 ```js
166 import { Readable } from 'node:stream';
167
168 new Promise((resolve, reject) => {
169 Readable.from(stringifyChunked(data))
170 .on('error', reject)
171 .pipe(stream)
172 .on('error', reject)
173 .on('finish', resolve);
174 });
175 ```
176- Writing into a file synchronously:
177 > Note: Slower than `JSON.stringify()` but uses much less heap space and has no limitation on string length
178 ```js
179 import fs from 'node:fs';
180
181 const fd = fs.openSync('output.json', 'w');
182
183 for (const chunk of stringifyChunked(data)) {
184 fs.writeFileSync(fd, chunk);
185 }
186
187 fs.closeSync(fd);
188 ```
189- Using with fetch (JSON streaming):
190 > Note: This feature has limited support in browsers, see [Streaming requests with the fetch API](https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests)
191
192 > Note: `ReadableStream.from()` has limited [support in browsers](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/from_static), use [`createStringifyWebStream()`](#createstringifywebstream) instead.
193 ```js
194 fetch('http://example.com', {
195 method: 'POST',
196 duplex: 'half',
197 body: ReadableStream.from(stringifyChunked(data))
198 });
199 ```
200- Wrapping into `ReadableStream`:
201 > Note: Use `ReadableStream.from()` or [`createStringifyWebStream()`](#createstringifywebstream) when no extra logic is needed
202 ```js
203 new ReadableStream({
204 start() {
205 this.generator = stringifyChunked(data);
206 },
207 pull(controller) {
208 const { value, done } = this.generator.next();
209
210 if (done) {
211 controller.close();
212 } else {
213 controller.enqueue(value);
214 }
215 },
216 cancel() {
217 this.generator = null;
218 }
219 });
220 ```
221
222### stringifyInfo()
223
224```ts
225export function stringifyInfo(value: any, replacer?: Replacer, space?: Space): StringifyInfoResult;
226export function stringifyInfo(value: any, options?: StringifyInfoOptions): StringifyInfoResult;
227
228type StringifyInfoOptions = {
229 replacer?: Replacer;
230 space?: Space;
231 continueOnCircular?: boolean;
232}
233type StringifyInfoResult = {
234 bytes: number; // size of JSON in bytes
235 spaceBytes: number; // size of white spaces in bytes (when space option used)
236 circular: object[]; // list of circular references
237};
238```
239
240Functions like [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), but returns an object with the expected overall size of the stringify operation and a list of circular references.
241
242Example:
243
244```js
245import { stringifyInfo } from '@discoveryjs/json-ext';
246
247console.log(stringifyInfo({ test: true }, null, 4));
248// {
249// bytes: 20, // Buffer.byteLength('{\n "test": true\n}')
250// spaceBytes: 7,
251// circular: []
252// }
253```
254
255#### Options
256
257##### continueOnCircular
258
259Type: `Boolean`
260Default: `false`
261
262Determines whether to continue collecting info for a value when a circular reference is found. Setting this option to `true` allows finding all circular references.
263
264### parseFromWebStream()
265
266A helper function to consume JSON from a Web Stream. You can use `parseChunked(stream)` instead, but `@@asyncIterator` on `ReadableStream` has limited support in browsers (see [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) compatibility table).
267
268```js
269import { parseFromWebStream } from '@discoveryjs/json-ext';
270
271const data = await parseFromWebStream(readableStream);
272// equivalent to (when ReadableStream[@@asyncIterator] is supported):
273// await parseChunked(readableStream);
274```
275
276### createStringifyWebStream()
277
278A helper function to convert `stringifyChunked()` into a `ReadableStream` (Web Stream). You can use `ReadableStream.from()` instead, but this method has limited support in browsers (see [ReadableStream.from()](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/from_static) compatibility table).
279
280```js
281import { createStringifyWebStream } from '@discoveryjs/json-ext';
282
283createStringifyWebStream({ test: true });
284// equivalent to (when ReadableStream.from() is supported):
285// ReadableStream.from(stringifyChunked({ test: true }))
286```
287
288## License
289
290MIT
Note: See TracBrowser for help on using the repository browser.