fast-json-stable-stringify vs json-stable-stringify vs json-stable-stringify-without-jsonify
Stable JSON Stringification Libraries for Deterministic Serialization
fast-json-stable-stringifyjson-stable-stringifyjson-stable-stringify-without-jsonify

Stable JSON Stringification Libraries for Deterministic Serialization

fast-json-stable-stringify, json-stable-stringify, and json-stable-stringify-without-jsonify are all npm packages designed to produce deterministic, canonical JSON strings by recursively sorting object keys before serialization. This is essential for use cases like generating consistent cache keys, computing object hashes, or comparing data structures where property order must not affect the output. While they share the same core goal, they differ significantly in performance characteristics, dependency footprint, and support for advanced features like custom comparators, pretty printing, and circular reference handling.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
fast-json-stable-stringify82,407,444320-256 years agoMIT
json-stable-stringify07836.4 kB710 months agoMIT
json-stable-stringify-without-jsonify013-19 years agoMIT

Stable JSON Stringification in JavaScript: A Practical Comparison

When you need to generate a consistent, deterministic string representation of a JavaScript object — regardless of property order — standard JSON.stringify() won’t cut it. That’s where stable stringification libraries come in. The three packages under review — fast-json-stable-stringify, json-stable-stringify, and json-stable-stringify-without-jsonify — all aim to solve this problem, but with different trade-offs in performance, dependencies, and compatibility. Let’s dig into how they work and where each shines.

🔤 What Is Stable Stringification?

Normal JSON.stringify() outputs properties in the order they appear in the object (which may vary across engines or even runs). For use cases like caching, hashing, or comparing object equality, you need a canonical form — one that always produces the same string for the same logical data. Stable stringifiers sort object keys recursively before serializing, ensuring deterministic output.

All three packages do this, but their implementation strategies differ significantly.

⚙️ Core Implementation Differences

json-stable-stringify

This is the original, widely used implementation. It supports custom comparison functions, circular reference detection, and works in both Node.js and browsers. However, it depends on the jsonify package for safe JSON serialization.

const stringify = require('json-stable-stringify');

const obj = { b: 2, a: 1 };
console.log(stringify(obj)); // '{"a":1,"b":2}'

// With custom comparator
console.log(stringify(obj, { cmp: (a, b) => a.key < b.key ? 1 : -1 }));

fast-json-stable-stringify

As the name suggests, this package prioritizes speed. It avoids external dependencies (including jsonify) and uses a highly optimized algorithm based on iterative sorting and manual string building. It does not support custom comparators or circular references, but it’s significantly faster for plain objects.

const stringify = require('fast-json-stable-stringify');

const obj = { z: 3, a: 1, m: 2 };
console.log(stringify(obj)); // '{"a":1,"m":2,"z":3}'

// No options supported — just pass the object

json-stable-stringify-without-jsonify

This is a direct fork of json-stable-stringify that removes the jsonify dependency. The API and features are identical to the original, but it uses native JSON.stringify() internally instead of jsonify. This makes it lighter and avoids potential compatibility issues with older environments where jsonify might behave unexpectedly.

const stringify = require('json-stable-stringify-without-jsonify');

const obj = { name: 'Alice', id: 42 };
console.log(stringify(obj)); // '{"id":42,"name":"Alice"}'

// Supports same options as json-stable-stringify
console.log(stringify(obj, { space: 2 }));

🧪 Feature Comparison

Featurejson-stable-stringifyfast-json-stable-stringifyjson-stable-stringify-without-jsonify
Key sorting
Custom comparator (cmp)
Pretty printing (space)
Circular reference handling
No external dependencies❌ (jsonify)
Browser compatibility
Performance (plain objects)ModerateFastestModerate

🛠️ Real-World Usage Scenarios

Scenario 1: High-Performance Caching Layer

You’re building a Redis-based cache key generator from request payloads. Speed is critical, and inputs are plain JSON-compatible objects (no cycles, no functions).

  • Best choice: fast-json-stable-stringify
  • Why? Maximum throughput with minimal overhead.
const fastStringify = require('fast-json-stable-stringify');
const cacheKey = fastStringify(request.body);

Scenario 2: Debugging or Logging with Readable Output

You need stable stringification for object diffs in logs, and want optional pretty-printing for readability during development.

  • Best choice: json-stable-stringify-without-jsonify
  • Why? Same API as the original but without the jsonify dependency, and supports space option.
const stringify = require('json-stable-stringify-without-jsonify');
console.log(stringify(diffObject, { space: 2 }));

Scenario 3: Complex Object Graphs with Cycles

Your application processes user-defined object trees that may contain circular references (e.g., DOM-like structures in a visual editor).

  • Best choice: json-stable-stringify or json-stable-stringify-without-jsonify
  • Why? Only these two detect and handle circular references safely.
const a = {};
const b = { parent: a };
a.child = b;

// Without cycle handling, this would crash
stringify(a); // Both jsonify-based packages handle this gracefully

⚠️ Important Notes on Maintenance

As of the latest npm registry data:

  • json-stable-stringify is still maintained and widely used.
  • fast-json-stable-stringify is actively maintained, with recent updates focused on performance and correctness.
  • json-stable-stringify-without-jsonify appears to be a community fork with no official deprecation notice, but has fewer updates. It remains functionally sound for its stated purpose.

None of these packages are officially deprecated, so all are viable for production use — provided you match the feature set to your needs.

💡 Final Guidance

  • If you need raw speed and your data is simple (no cycles, no custom sorting), go with fast-json-stable-stringify.
  • If you need full feature parity with the original (custom comparators, pretty printing, cycle detection) and want to avoid the jsonify dependency, choose json-stable-stringify-without-jsonify.
  • If you’re already using json-stable-stringify and have no issues with jsonify, there’s no urgent need to switch — but consider the -without-jsonify variant if you encounter environment-specific quirks.

In practice, most frontend applications dealing with API payloads or state snapshots will benefit from the speed of fast-json-stable-stringify. Reserve the more feature-rich options for tooling, debugging, or complex data processing scenarios.

How to Choose: fast-json-stable-stringify vs json-stable-stringify vs json-stable-stringify-without-jsonify

  • fast-json-stable-stringify:

    Choose fast-json-stable-stringify when you need maximum performance for serializing plain, JSON-compatible objects without circular references. It has zero dependencies and is ideal for high-throughput scenarios like cache key generation or state hashing in frontend applications where input data is well-controlled.

  • json-stable-stringify:

    Choose json-stable-stringify if you require advanced features like custom key comparators, pretty printing with indentation, or built-in circular reference detection, and you're comfortable with its dependency on the jsonify package. It's suitable for debugging tools, complex data processing, or environments where full compatibility with the original stable stringify behavior is needed.

  • json-stable-stringify-without-jsonify:

    Choose json-stable-stringify-without-jsonify when you want all the features of json-stable-stringify — including custom sorting and cycle detection — but prefer to avoid the jsonify dependency. This makes it a safer drop-in replacement in browser environments or projects sensitive to transitive dependencies, while maintaining the same API.

README for fast-json-stable-stringify

fast-json-stable-stringify

Deterministic JSON.stringify() - a faster version of @substack's json-stable-strigify without jsonify.

You can also pass in a custom comparison function.

Build Status Coverage Status

example

var stringify = require('fast-json-stable-stringify');
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
console.log(stringify(obj));

output:

{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}

methods

var stringify = require('fast-json-stable-stringify')

var str = stringify(obj, opts)

Return a deterministic stringified string str from the object obj.

options

cmp

If opts is given, you can supply an opts.cmp to have a custom comparison function for object keys. Your function opts.cmp is called with these parameters:

opts.cmp({ key: akey, value: avalue }, { key: bkey, value: bvalue })

For example, to sort on the object key names in reverse order you could write:

var stringify = require('fast-json-stable-stringify');

var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
var s = stringify(obj, function (a, b) {
    return a.key < b.key ? 1 : -1;
});
console.log(s);

which results in the output string:

{"c":8,"b":[{"z":6,"y":5,"x":4},7],"a":3}

Or if you wanted to sort on the object values in reverse order, you could write:

var stringify = require('fast-json-stable-stringify');

var obj = { d: 6, c: 5, b: [{z:3,y:2,x:1},9], a: 10 };
var s = stringify(obj, function (a, b) {
    return a.value < b.value ? 1 : -1;
});
console.log(s);

which outputs:

{"d":6,"c":5,"b":[{"z":3,"y":2,"x":1},9],"a":10}

cycles

Pass true in opts.cycles to stringify circular property as __cycle__ - the result will not be a valid JSON string in this case.

TypeError will be thrown in case of circular object without this option.

install

With npm do:

npm install fast-json-stable-stringify

benchmark

To run benchmark (requires Node.js 6+):

node benchmark

Results:

fast-json-stable-stringify x 17,189 ops/sec ±1.43% (83 runs sampled)
json-stable-stringify x 13,634 ops/sec ±1.39% (85 runs sampled)
fast-stable-stringify x 20,212 ops/sec ±1.20% (84 runs sampled)
faster-stable-stringify x 15,549 ops/sec ±1.12% (84 runs sampled)
The fastest is fast-stable-stringify

Enterprise support

fast-json-stable-stringify package is a part of Tidelift enterprise subscription - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers.

Security contact

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerability via GitHub issues.

license

MIT