Deterministic JSON.stringify() to get deterministic hashes from stringified results
npx @tessl/cli install tessl/npm-json-stable-stringify@1.0.0Fast JSON Stable Stringify provides a deterministic version of JSON.stringify() that produces consistent output for the same input, enabling reliable hash generation from stringified JSON objects. It addresses the inherent non-deterministic behavior of standard JSON.stringify() by sorting object keys in a consistent order.
npm install json-stable-stringifyconst stringify = require('json-stable-stringify');const stringify = require('json-stable-stringify');
// Basic usage - keys are sorted alphabetically
const obj = { c: 8, b: [4, 5], a: 3 };
const result = stringify(obj);
console.log(result); // {"a":3,"b":[4,5],"c":8}
// With pretty printing
const prettyResult = stringify(obj, { space: ' ' });
console.log(prettyResult);
// {
// "a": 3,
// "b": [
// 4,
// 5
// ],
// "c": 8
// }Creates a deterministic string representation of JavaScript objects by consistently sorting object keys.
/**
* Creates a deterministic string representation of JavaScript objects
* @param {any} obj - The JavaScript value to stringify. Objects with toJSON methods will have those methods called automatically
* @param {object|function} [opts] - Options object or comparison function
* @returns {string|undefined} Deterministic JSON string representation
*/
function stringify(obj, opts);interface StringifyOptions {
/** Custom comparison function for object key sorting */
cmp?: (a: CompareObject, b: CompareObject) => number;
/** Indentation for pretty-printing (string or number of spaces) */
space?: string | number;
/** Whether to handle circular references (default: false) */
cycles?: boolean;
/** Custom value transformation function */
replacer?: (key: string, value: any) => any;
}
interface CompareObject {
/** The object key being compared */
key: string;
/** The value associated with the key */
value: any;
}opts.cycles is false or undefined. Error message: "Converting circular structure to JSON"toJSON methods are automatically called during stringificationconst stringify = require('json-stable-stringify');
const obj = { c: 8, b: [4, 5], a: 3 };
// Reverse alphabetical key sorting
const result = stringify(obj, function (a, b) {
return a.key < b.key ? 1 : -1;
});
console.log(result); // {"c":8,"b":[4,5],"a":3}
// Sort by value (descending)
const obj2 = { d: 6, c: 5, b: 4, a: 10 };
const result2 = stringify(obj2, function (a, b) {
return a.value < b.value ? 1 : -1;
});
console.log(result2); // {"a":10,"d":6,"c":5,"b":4}const stringify = require('json-stable-stringify');
const obj = { b: 1, a: { foo: 'bar', and: [1, 2, 3] } };
// Using string indentation
const result1 = stringify(obj, { space: ' ' });
// Using number of spaces
const result2 = stringify(obj, { space: 4 });
// Using tab character
const result3 = stringify(obj, { space: '\t' });const stringify = require('json-stable-stringify');
const obj = {
name: 'John',
password: 'secret123',
age: 30,
internal: 'hidden'
};
// Remove sensitive fields
const result = stringify(obj, {
replacer: function(key, value) {
if (key === 'password' || key === 'internal') {
return undefined; // Exclude from output
}
return value;
}
});
console.log(result); // {"age":30,"name":"John"}Objects with toJSON methods are automatically processed during stringification, similar to native JSON.stringify().
const stringify = require('json-stable-stringify');
// Object with toJSON method returning object
const obj1 = {
one: 1,
two: 2,
toJSON: function() {
return { one: 1 };
}
};
console.log(stringify(obj1)); // {"one":1}
// Object with toJSON method returning string
const obj2 = {
one: 1,
two: 2,
toJSON: function() {
return 'one';
}
};
console.log(stringify(obj2)); // "one"
// Object with toJSON method returning array
const obj3 = {
one: 1,
two: 2,
toJSON: function() {
return ['one'];
}
};
console.log(stringify(obj3)); // ["one"]const stringify = require('json-stable-stringify');
const obj = { a: 1 };
obj.circular = obj; // Create circular reference
// With cycles: true - circular references become "__cycle__"
const safe = stringify(obj, { cycles: true });
console.log(safe); // {"a":1,"circular":"__cycle__"}
// With cycles: false (default) - throws TypeError
try {
const unsafe = stringify(obj);
} catch (error) {
console.log(error.message); // "Converting circular structure to JSON"
}const stringify = require('json-stable-stringify');
const obj = { c: 8, b: [{ z: 6, y: 5, x: 4 }, 7], a: 3 };
const result = stringify(obj, {
space: 2,
cmp: function(a, b) {
return a.key < b.key ? -1 : 1; // Alphabetical sorting
},
replacer: function(key, value) {
// Convert numbers to strings
return typeof value === 'number' ? String(value) : value;
}
});