npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

json-off-thread

v1.0.23

Published

Non-blocking JSON extension for Node.js.

Downloads

193

Readme

JSON-Off-Thread

High-performance, asynchronous JSON utilities for Node.js using native addon + RapidJSON. Provides both standard promise-based parse/stringify and streaming APIs with cancellation, backpressure, and advanced type policies.

Features

  • Non-blocking stringify and parse off the main thread.
  • stringifyStream(object, options) incremental emission of JSON string chunks.
  • parseStream(jsonString, options) incremental emission of top-level or deep nested values.
  • Backpressure via Promise return (automatic) or manual resume() control.
  • Cancellation tokens (createStringifyToken + cancelStringify).
  • BigInt policies: wrap | string | number | ignore.
  • Date policies: wrap | iso | epoch.
  • Precise UTC ISO date format: YYYY-MM-DDTHH:MM:SS.mmmZ.
  • Deep streaming parse traversal (mode: 'deep').

Installation

    npm i json-off-thread

API

stringify(value, [options]) -> Promise

Options:

  • pretty: boolean pretty-print output.
  • token: number cancellation token id.

parse(jsonString) -> Promise

Standard full parse returning JS value.

stringifyStream(value, options) -> Promise

Emits chunks of the JSON string during serialization. Options:

  • onChunk(chunk: string[, control]) required. If returns a Promise, traversal waits until it resolves (automatic backpressure). If backpressureManual: true, a second control argument with resume() is provided instead.
  • chunkSize: number threshold (>=1024) in bytes before flushing.
  • pretty: boolean pretty-print.
  • token: number cancellation token.
  • backpressureManual: boolean manual mode.
  • bigIntStrategy: 'wrap'|'string'|'number'|'ignore'
  • dateStrategy: 'wrap'|'iso'|'epoch'

Returns: Final aggregated JSON string (or rejects on cancel/error).

parseStream(jsonString, options) -> Promise

Streams parsed values. Options:

  • onValue(value: any[, keyOrIndex, control]) required.
    • Default: value is a JSON string snippet. keyOrIndex is not provided.
    • If emitNative: true: value is the JS object/value. keyOrIndex is the property name (string) or array index (number) if applicable.
  • emitNative: boolean default false. If true, converts JSON to JS objects on the main thread before emission.
  • mode: 'top'|'deep' default top.
  • backpressureManual: boolean manual resume control.
  • token: number cancellation token.

Resolves with the full original JSON string when complete.

createStringifyToken() -> number

Generates a token for cancellation.

cancelStringify(tokenId)

Sets the token flag to abort current operation (applies to both streaming and non-streaming when token passed).

Backpressure Modes

  1. Automatic: Return a Promise from onChunk / onValue; traversal pauses until resolve/reject.
  2. Manual: Set backpressureManual: true. Your handler receives (chunk, control) or (valueJSON, control); call control.resume() to continue.

BigInt Policy Details

  • wrap: Encoded as {"$bigint":"<digits>"} for round-trip safety.
  • string: Direct JSON string digits.
  • number: 64-bit number (potential precision loss for >53-bit values).
  • ignore: Serialized as null.

Date Policy Details

  • wrap: {"$date":"<epoch_ms>"} as string.
  • iso: Precise UTC ISO string YYYY-MM-DDTHH:MM:SS.mmmZ.
  • epoch: 64-bit integer milliseconds since epoch.

Deep Parse Streaming

When mode: 'deep', parseStream performs a depth-first traversal emitting nested values (objects/arrays emitted after their children). Useful for progressive loading or indexing.

Example

const addon = require('json-off-thread');

// Streaming stringify with promise backpressure
addon.stringifyStream(largeObj, {
    chunkSize: 8192,
    onChunk: (chunk) => {
        // write to socket
        return writeAsync(chunk); // returns Promise
    },
    bigIntStrategy: 'wrap',
    dateStrategy: 'iso'
}).then(final => console.log('Done len', final.length));

// Manual backpressure
addon.stringifyStream(largeObj, {
    chunkSize: 4096,
    backpressureManual: true,
    onChunk: (chunk, control) => {
        queue.push(chunk);
        if (queue.length < 10) control.resume(); // continue immediately
        else flushQueue().then(()=>control.resume());
    }
});

// Streaming parse deep
addon.parseStream(JSON.stringify(largeStructure), {
    mode: 'deep',
    onValue: (json, control) => {
        index(json);
        control && control.resume();
    },
    backpressureManual: true
});

Notes / Limitations

  • Default parse streaming emits serialized JSON snippets. Use emitNative: true to receive live JS values (note: conversion happens on main thread).
  • Deep mode order: children before parent containers.
  • Cancellation checks occur between emissions; very large single values (huge strings) may not be interruptible mid-write.
  • Backpressure sleep interval is 5ms; adjust if you need tighter latency.

Future Ideas

  • Adjustable sleep/yield strategy (adaptive).
  • Max depth / size guards for security.
  • Pure streaming (no aggregation) option returning metadata.

License

MIT (add your chosen license here).