Skip to content

Migrating from 2.x to 3.x

Eugene Lazutkin edited this page May 21, 2026 · 6 revisions

Migrating from 2.x to 3.x

stream-json 3.0 is an ESM-only release that rebases the library on stream-chain 4.x and drops CommonJS access.

The runtime APIs, factory shapes, token vocabulary, and per-module export structure are unchanged. Most code only needs the require()import rewrite and Node version bump.

What changed

Area 2.x 3.x
Module type "type": "commonjs" "type": "module"
Minimum Node >=14 (de facto) >=22
stream-chain ^3.6.0 ^4.0.0
Consumer access require() and import import only
Test files (in repo) .mjs / .mts .js / .ts

What didn't change

  • The factory pattern for every module (parser(), pick(), streamArray(), verifier(), etc.).
  • .asStream(options), .withParser(options), .withParserAsStream(options) static methods.
  • The token protocol — {name, value} shapes, the token vocabulary, and assembler semantics.
  • TypeScript namespace types like parser.Token, parser.ParserOptions, streamArray.StreamArrayItem continue to work; they are now also re-exported as top-level type names for ESM-style imports.
  • Assembler and FlexAssembler are still classes; Assembler.connectTo(stream, options) works as before.
  • Module paths under stream-json/... are unchanged.

Migration: require()import

The minimal change is a syntactic rewrite. The same module paths and named bindings work.

Main entry point

// 2.x (CJS)
const make = require('stream-json');
const {parser} = require('stream-json');

// 3.x (ESM)
import make from 'stream-json';
import {parser} from 'stream-json';

Core components

// 2.x
const Assembler = require('stream-json/assembler.js');
const {disassembler} = require('stream-json/disassembler.js');
const stringer = require('stream-json/stringer.js');
const emitter = require('stream-json/emitter.js');

// 3.x
import Assembler from 'stream-json/assembler.js';
import {disassembler} from 'stream-json/disassembler.js';
import stringer from 'stream-json/stringer.js';
import emitter from 'stream-json/emitter.js';

Filters

// 2.x
const {pick} = require('stream-json/filters/pick.js');
const {replace} = require('stream-json/filters/replace.js');
const {ignore} = require('stream-json/filters/ignore.js');
const {filter} = require('stream-json/filters/filter.js');

// 3.x
import {pick} from 'stream-json/filters/pick.js';
import {replace} from 'stream-json/filters/replace.js';
import {ignore} from 'stream-json/filters/ignore.js';
import {filter} from 'stream-json/filters/filter.js';

Streamers

// 2.x
const {streamValues} = require('stream-json/streamers/stream-values.js');
const {streamArray} = require('stream-json/streamers/stream-array.js');
const {streamObject} = require('stream-json/streamers/stream-object.js');

// 3.x
import {streamValues} from 'stream-json/streamers/stream-values.js';
import {streamArray} from 'stream-json/streamers/stream-array.js';
import {streamObject} from 'stream-json/streamers/stream-object.js';

Utilities

// 2.x
const emit = require('stream-json/utils/emit.js');
const withParser = require('stream-json/utils/with-parser.js');
const batch = require('stream-json/utils/batch.js');
const verifier = require('stream-json/utils/verifier.js');
const Utf8Stream = require('stream-json/utils/utf8-stream.js');
const FlexAssembler = require('stream-json/utils/flex-assembler.js');

// 3.x
import emit from 'stream-json/utils/emit.js';
import withParser from 'stream-json/utils/with-parser.js';
import batch from 'stream-json/utils/batch.js';
import verifier from 'stream-json/utils/verifier.js';
import Utf8Stream from 'stream-json/utils/utf8-stream.js';
import FlexAssembler from 'stream-json/utils/flex-assembler.js';

JSONL / JSONC

// 2.x
const jsonlParser = require('stream-json/jsonl/parser.js');
const jsonlStringer = require('stream-json/jsonl/stringer.js');
const jsoncParser = require('stream-json/jsonc/parser.js');
const jsoncStringer = require('stream-json/jsonc/stringer.js');
const jsoncVerifier = require('stream-json/jsonc/verifier.js');

// 3.x
import jsonlParser from 'stream-json/jsonl/parser.js';
import jsonlStringer from 'stream-json/jsonl/stringer.js';
import jsoncParser from 'stream-json/jsonc/parser.js';
import jsoncStringer from 'stream-json/jsonc/stringer.js';
import jsoncVerifier from 'stream-json/jsonc/verifier.js';

Node.js version

3.0 requires Node.js 22 or later, matching stream-chain 4.x. The new minimum reflects the LTS floor at release time and unlocks native web-streams interop in stream-chain (stream-chain/web).

If your project is still on Node 14/16/18/20, stay on stream-json 2.x — it remains the supported branch for CJS / older-Node consumers.

stream-chain 4.x

stream-chain 4.x is the underlying pipeline library. stream-json 3.0 picks up its new module type, ESM exports, and lifted symbols automatically:

  • The default export is still chain.
  • The top-level export surface (asStream, gen, flushable, none, many, combineManyMut, getManyValues, isMany, etc.) is unchanged from the names stream-json consumes.
  • New subpaths (stream-chain/web, stream-chain/core) are available if you want web-streams-based pipelines; stream-json itself remains Node-streams-based.

See the stream-chain 4.0 release notes for details.

Stuck on CJS?

require('stream-json') from a CJS file is no longer supported. Three options:

  1. Convert the consumer to ESM. Add "type": "module" to your package.json and switch require()import. The same module paths still resolve.
  2. Use Node 22.12+ require(esm) flag. Recent Node versions can require() an ESM module under --experimental-require-module. Not a long-term recommendation.
  3. Stay on stream-json 2.x. It remains available on npm and is the maintained CJS line.

TypeScript

Type imports continue to work. Both styles are supported:

// Namespace style (worked in 2.x, still works in 3.x)
import parser from 'stream-json/parser.js';
const t: parser.Token = {name: 'startObject'};
const opts: parser.ParserOptions = {jsonStreaming: true};

// Named-import style (recommended in 3.x)
import {parser, type Token, type ParserOptions} from 'stream-json/parser.js';
const t: Token = {name: 'startObject'};
const opts: ParserOptions = {jsonStreaming: true};

Set your project's tsconfig.json to "module": "node16" (or "nodenext") and "moduleResolution": "node16" so that the .js extensions in stream-json's type declarations resolve correctly.

See also

Clone this wiki locally