-
-
Notifications
You must be signed in to change notification settings - Fork 53
Stringer
Signature: tokens → text
Stringer consumes a token stream and converts it to text representing a JSON object. stringer() returns a function for use in chain(). stringer.asStream() wraps it as a Duplex stream. It is very useful when you want to edit a stream with filters and custom code, and save it back to a file.
If Parser corresponds to JSON.parse(), then Stringer corresponds to JSON.stringify(). However, it will only convert a stream of tokens generated by Parser. Feeding raw objects into Stringer will output empty strings.
To output JSONL instead of regular JSON, use stream-chain's JSONL stringer.
Stringer accepts multiple top-level values (e.g. the output of a jsonStreaming parser): they are written back-to-back as Concatenated JSON, with a space before bare numbers so adjacent values cannot merge — the input {"a":1} [2] "x" 3 comes out as {"a":1}[2]"x" 3. Use makeArray: true to wrap the values into a single valid JSON array instead: [{"a":1},[2],"x",3].
import {stringer} from 'stream-json/stringer.js';
import {parser} from 'stream-json';
import chain from 'stream-chain';
import {pick} from 'stream-json/filters/pick.js';
import fs from 'node:fs';
import zlib from 'node:zlib';
chain([
fs.createReadStream('data.json.gz'),
zlib.createGunzip(),
parser(),
pick({filter: 'data'}),
stringer(),
zlib.createGzip(),
fs.createWriteStream('edited.json.gz')
]);Stringer has no special API. The writable side operates in object mode and the readable side produces text.
options is an optional object. The following custom flags are recognized (all truthy/falsy, default false):
-
useValuesserves as the initial value for selecting packed or streamed values of strings, numbers, and keys. -
useKeyValuesspecifies, if we need to use packed keys or streamed ones. -
useStringValuesspecifies, if we need to use packed strings or streamed ones. -
useNumberValuesspecifies, if we need to use packed numbers or streamed ones. -
makeArray(since 1.4.0) forces all incoming JSON objects to be wrapped in an array.- If no input, an empty array will be produced.
By default Stringer converts chunks to strings and outputs them. But it is possible to force it to use packed values instead of streamed chunks, providing that an upstream sends packed values. In some cases, when no streamed chunks are present in a token stream, we have to force the use of values.
Rule of thumb for a long pipeline: mirror the parser. With default parser settings (values streamed and packed) Stringer's defaults just work. If the parser was configured with streamXXX: false (packed only), set the matching useXXXValues: true — there are no chunks left to consume. Filters pass tokens through in the shape they received, so the parser's settings are normally what count end-to-end.
Internally each type of value is controlled by a flag:
- By default, this flag is
false. - If
useValuesis set, it is assigned to each flag. - If an individual option is set, it is assigned to the flag.
Examples:
| Supplied options | useKeyValues |
useStringValues |
useNumberValues |
|---|---|---|---|
{} |
false |
false |
false |
{useValues: true} |
true |
true |
true |
{useValues: true, useKeyValues: false} |
false |
true |
true |
{useKeyValues: false, useValues: true} |
false |
true |
true |
{useStringValues: true} |
false |
true |
false |
{useKeyValues: true, useStringValues: false, useNumberValues: true} |
true |
false |
true |
Alias of the factory function.
Returns a Duplex stream suitable for .pipe() usage.
import stringer from 'stream-json/stringer.js';
import chain from 'stream-chain';
import {parser} from 'stream-json';
import {pick} from 'stream-json/filters/pick.js';
import fs from 'node:fs';
const pipeline = chain([fs.createReadStream('sample.json'), parser(), pick({filter: 'data'}), stringer()]);stringer ships in two substrate-specific entries with the same factory shape:
-
Node —
stream-json/stringer.js. HasasStream(Node Duplex) andasWebStream(Web{readable, writable}pair). -
Web —
stream-json/web/stringer.js. HasasWebStreamonly. Pulls in no Node-stream imports.
Both factories return the same flushable, so chain on either substrate auto-wraps it. Use chain from stream-chain on Node and from stream-chain/web on Web.
// Web
import {chain} from 'stream-chain/web';
import {parser} from 'stream-json/web/parser.js';
import {pick} from 'stream-json/web/filters/pick.js';
import {stringer} from 'stream-json/web/stringer.js';
const pipeline = chain([source, parser(), pick({filter: 'data'}), stringer()]);
let result = '';
for await (const chunk of pipeline.readable) result += chunk;
console.log(result);Start here
Core
Filters
Streamers
Essentials
Utilities
File I/O (Node-only)
JSONC
JSONL (use stream-chain)
Reference
Built on stream-chain