Skip to content

Migrating from 0.x to 1.x

Arshavir Ter-Gabrielyan edited this page Apr 15, 2021 · 4 revisions

This page hosts hints on migrating from 0.x to 1.x. If you feel that some fine points are missing or covered incorrectly, please suggest an edit.

Parsing

Parsers of 0.x produced a low-level token stream, which was then assembled in a high-level token stream by Streamer and optionally values were packed by Packer. It turned out that the vast majority of projects used those three components together. So for performance reasons Combo was created, which logically combined all three of them.

In 1.x Parser serves the same function as Combo 0.x, and uses similar options. It can emulate a parser + Streamer + Packer, or a parser + Streamer, but not an old parser alone. Using a low-level token stream helped to debug non-conformant JSON files. With 1.x it is suggested to use external JSON validators to debug syntax problems.

The streams produced by Parser 1.x and Combo 0.x are identical, so existing custom components can be reused.

One difference is how packing is turned on:

  • Combo 0.x does not pack any values by default. If you want packing, it should be enabled explicitly, e.g., {packKeys: true}.
  • Parser 1.x packs values by default. If you don't want it, it should be disabled explicitly, e.g., {packKeys: false}, or even {packValues: false}.

Filtering

Filter 0.x is nearly identical to Filter 1.x. One big difference is the old Filter assumed that keys fit memory, and packed them automatically. The new Filter doesn't do that but assumes that an upstream produces packed key values if a filter function requires them. Don't forget to enable them.

Streaming

StreamArray

StreamArray 0.x can be emulated with StreamArray 1.x without a filter option. The only significant difference is that the 0.x version produced data objects like {index: N, value: item}, while the 1.x version produces data objects {key: N, value: item}. Save for the renaming the rest is logically the same.

StreamFilteredArray

StreamFilteredArray 0.x can be emulated with StreamArray 1.x with a filter option:

// we want to filter a stream like that:
// [1, 0, [], {x: 1, a: 'accept'}, {y: 2, a: 'reject'}, {z: 3, a: 'neutral'}]
// we need to accept all objects, reject all with 'a' equals 'reject',
// and reject everything else.

const objectFilter = asm => {
  if (asm.stack.length == 2 && asm.key === null && asm.current) {
    if (asm.current instanceof Array) {
      return false;
    }
    switch (asm.current.a) {
      case 'accept': return true;
      case 'reject': return false;
    }
  }
};

// 0.x:
const streamer0 = new StreamFilteredArray({objectFilter});

// 1.x:
const streamer1 = new StreamArray({objectFilter, includeUndecided: true});

Assembler 1.x has new properties and methods, which can be used in an object filter, like depth. Review new API to see, if you can take advantage of new facilities.

StreamObject

StreamObject 0.x can be emulated with StreamObject 1.x without a filter option.

StreamJsonObjects

StreamJsonObjects 0.x can be emulated with StreamValues 1.x without a filter option. The only significant difference is that StreamJsonObjects produced data objects like {index: N, value: item}, while StreamValues produces data objects {key: N, value: item}. Save for the renaming the rest is logically the same.

Miscellaneous

Assembler

Both versions of Assembler are logically identical. The major difference is that Assembler 1.x has more public properties and methods.

Stringer

Both versions of Stringer are logically identical. The major difference is that Stringer 1.x has more options for customizing its behavior.

Emitter

Both versions of Emitter are logically identical.

FilterObjects

There is no component directly corresponding to FilterObjects 0.x. It can be easily done with stream-chain:

// We filter out all even items 

// 0.x:
fs.createReadStream('sample.json')
  .pipe(new Combo({packKeys: true, packStrings: true, packNumbers: true}))
  .pipe(new StreamArray())
  .pipe(new FilterObject({itemFilter: data => data.index % 2}));

// 1.x
const chain = require('stream-chain');
chain([
  fs.createReadStream('sample.json'),
  new Parser(),
  new StreamArray(),
  data => data.key % 2
]);

Source

There is no component directly corresponding to Source 0.x. It can be easily done with stream-chain and emit():

// 0.x
const Source = require('stream-json/Source');
const source = new Source([parserStream, filterStream]);
fs.createReadStream('sample.json').pipe(source.input);

let counter = 0;
source.on('startObject', () => ++counter);
source.on('end', () => console.log(`We have ${counter} objects.`));

// 1.x
const chain = require('stream-chain');
const emit  = require('stream-json/itils/emit');

const pipeline = emit(chain([
  fs.createReadStream('sample.json'),
  parserStream,
  filterStream
]));

let counter = 0;
pipeline.on('startObject', () => ++counter);
pipeline.on('end', () => console.log(`We have ${counter} objects.`));
Clone this wiki locally