json-stable-stringify
Advanced tools
Comparing version
@@ -8,2 +8,13 @@ # Changelog | ||
## [v1.3.0](https://github.com/ljharb/json-stable-stringify/compare/v1.2.1...v1.3.0) - 2025-04-21 | ||
### Fixed | ||
- [New] add `collapseEmpty` option [`#15`](https://github.com/ljharb/json-stable-stringify/issues/15) | ||
### Commits | ||
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape` [`1ac9c16`](https://github.com/ljharb/json-stable-stringify/commit/1ac9c164666d4f70b216de0a7bb142ced5de2995) | ||
- [Deps] update `call-bound` [`729fcba`](https://github.com/ljharb/json-stable-stringify/commit/729fcba5d6f6b3b8599cc22e434272defc0a237f) | ||
## [v1.2.1](https://github.com/ljharb/json-stable-stringify/compare/v1.2.0...v1.2.1) - 2024-12-21 | ||
@@ -10,0 +21,0 @@ |
@@ -13,2 +13,3 @@ declare namespace stableStringify { | ||
cmp?: Comparator; | ||
collapseEmpty?: boolean; | ||
cycles?: boolean; | ||
@@ -15,0 +16,0 @@ replacer?: (this: Node, key: Key, value: unknown) => unknown; |
17
index.js
@@ -37,2 +37,6 @@ 'use strict'; | ||
var replacer = opts && opts.replacer ? callBind(opts.replacer) : defaultReplacer; | ||
if (opts && typeof opts.collapseEmpty !== 'undefined' && typeof opts.collapseEmpty !== 'boolean') { | ||
throw new TypeError('`collapseEmpty` must be a boolean, if provided'); | ||
} | ||
var collapseEmpty = !!opts && opts.collapseEmpty; | ||
@@ -70,3 +74,2 @@ var cmpOpt = typeof opts === 'function' ? opts : opts && opts.cmp; | ||
node = replacer(parent, key, node); | ||
if (node === undefined) { | ||
@@ -78,2 +81,10 @@ return; | ||
} | ||
/** @type {(out: string[], brackets: '[]' | '{}') => string} */ | ||
var groupOutput = function (out, brackets) { | ||
return collapseEmpty && out.length === 0 | ||
? brackets | ||
: (brackets === '[]' ? '[' : '{') + $join(out, ',') + indent + (brackets === '[]' ? ']' : '}'); | ||
}; | ||
if (isArray(node)) { | ||
@@ -85,3 +96,3 @@ var out = []; | ||
} | ||
return '[' + $join(out, ',') + indent + ']'; | ||
return groupOutput(out, '[]'); | ||
} | ||
@@ -114,5 +125,5 @@ | ||
$splice(seen, $indexOf(seen, node), 1); | ||
return '{' + $join(out, ',') + indent + '}'; | ||
return groupOutput(out, '{}'); | ||
}({ '': obj }, '', obj, 0) | ||
); | ||
}; |
{ | ||
"name": "json-stable-stringify", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "deterministic JSON.stringify() with custom sorting to get deterministic hashes from stringified results", | ||
@@ -46,3 +46,3 @@ "main": "index.js", | ||
"call-bind": "^1.0.8", | ||
"call-bound": "^1.0.3", | ||
"call-bound": "^1.0.4", | ||
"isarray": "^2.0.5", | ||
@@ -53,9 +53,9 @@ "jsonify": "^0.0.1", | ||
"devDependencies": { | ||
"@arethetypeswrong/cli": "^0.17.2", | ||
"@arethetypeswrong/cli": "^0.17.4", | ||
"@ljharb/eslint-config": "^21.1.1", | ||
"@ljharb/tsconfig": "^0.2.2", | ||
"@ljharb/tsconfig": "^0.3.2", | ||
"@types/call-bind": "^1.0.5", | ||
"@types/isarray": "^2.0.3", | ||
"@types/object-keys": "^1.0.3", | ||
"@types/tape": "^5.8.0", | ||
"@types/tape": "^5.8.1", | ||
"auto-changelog": "^2.5.0", | ||
@@ -62,0 +62,0 @@ "encoding": "^0.1.13", |
@@ -77,2 +77,27 @@ 'use strict'; | ||
test('space parameter base empty behavior: empty arrays and objects have added newline and space', function (t) { | ||
t.plan(1); | ||
var obj = { emptyArr: [], emptyObj: {} }; | ||
t.equal( | ||
stringify(obj, { space: ' ' }), | ||
'{\n "emptyArr": [\n ],\n "emptyObj": {\n }\n}' | ||
); | ||
}); | ||
test('space parameter, with collapseEmpty: true', function (t) { | ||
t.plan(2); | ||
var obj = { emptyArr: [], emptyObj: {} }; | ||
t['throws']( | ||
// @ts-expect-error | ||
function () { stringify(obj, { collapseEmpty: 'not a boolean' }); }, | ||
TypeError | ||
); | ||
t.equal( | ||
stringify(obj, { collapseEmpty: true, space: ' ' }), | ||
'{\n "emptyArr": [],\n "emptyObj": {}\n}' | ||
); | ||
}); | ||
test('space parameter, on a cmp function', function (t) { | ||
@@ -79,0 +104,0 @@ t.plan(3); |
36408
4.94%460
7.48%Updated