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.
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.
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.
json-stable-stringifyThis 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-stringifyAs 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-jsonifyThis 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 | json-stable-stringify | fast-json-stable-stringify | json-stable-stringify-without-jsonify |
|---|---|---|---|
| Key sorting | ✅ | ✅ | ✅ |
Custom comparator (cmp) | ✅ | ❌ | ✅ |
Pretty printing (space) | ✅ | ❌ | ✅ |
| Circular reference handling | ✅ | ❌ | ✅ |
| No external dependencies | ❌ (jsonify) | ✅ | ✅ |
| Browser compatibility | ✅ | ✅ | ✅ |
| Performance (plain objects) | Moderate | Fastest | Moderate |
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).
fast-json-stable-stringifyconst fastStringify = require('fast-json-stable-stringify');
const cacheKey = fastStringify(request.body);
You need stable stringification for object diffs in logs, and want optional pretty-printing for readability during development.
json-stable-stringify-without-jsonifyjsonify dependency, and supports space option.const stringify = require('json-stable-stringify-without-jsonify');
console.log(stringify(diffObject, { space: 2 }));
Your application processes user-defined object trees that may contain circular references (e.g., DOM-like structures in a visual editor).
json-stable-stringify or json-stable-stringify-without-jsonifyconst a = {};
const b = { parent: a };
a.child = b;
// Without cycle handling, this would crash
stringify(a); // Both jsonify-based packages handle this gracefully
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.
fast-json-stable-stringify.jsonify dependency, choose json-stable-stringify-without-jsonify.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.
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.
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.
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.
Deterministic JSON.stringify() - a faster version of @substack's json-stable-strigify without jsonify.
You can also pass in a custom comparison function.
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}
var stringify = require('fast-json-stable-stringify')
Return a deterministic stringified string str from the object obj.
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}
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.
With npm do:
npm install fast-json-stable-stringify
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
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.
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.