Skip to content

Commit

Permalink
Add spaceBytes field to stringifyInfo() result
Browse files Browse the repository at this point in the history
  • Loading branch information
lahmatiy committed Oct 17, 2024
1 parent 5dcb5c4 commit 835a9ba
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## next

- Added `spaceBytes` field to `stringifyInfo()` result, which indicates the number of bytes used for white spaces. This allows for estimating size of `JSON.stringify()` result with and without formatting (when `space` option is used) in a single pass instead of two
- Fixed `stringifyInfo()` to correctly accept the `space` parameter from options, i.e. `stringifyInfo(data, { space: 2 })`

## 0.6.1 (2024-08-06)
Expand Down
3 changes: 2 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ declare module '@discoveryjs/json-ext' {
}
type StringifyInfoResult = {
bytes: number;
circular: Object[];
spaceBytes: number;
circular: object[];
};

export function parseChunked(input: Iterable<Chunk> | AsyncIterable<Chunk>): Promise<any>;
Expand Down
18 changes: 13 additions & 5 deletions src/stringify-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export function stringifyInfo(value, optionsOrReplacer, space) {
const root = { '': value };
let stop = false;
let bytes = 0;
let spaceBytes = 0;
let objects = 0;

walk(root, '', value);
Expand All @@ -168,7 +169,8 @@ export function stringifyInfo(value, optionsOrReplacer, space) {
}

return {
bytes: isNaN(bytes) ? Infinity : bytes,
bytes: isNaN(bytes) ? Infinity : bytes + spaceBytes,
spaceBytes,
circular: [...circular]
};

Expand Down Expand Up @@ -232,7 +234,7 @@ export function stringifyInfo(value, optionsOrReplacer, space) {
let keyLen = keysLength.get(key);

if (keyLen === undefined) {
keysLength.set(key, keyLen = stringLength(key) + (space > 0 ? 2 : 1)); // "key":
keysLength.set(key, keyLen = stringLength(key) + 1); // "key":
}

// value is printed
Expand All @@ -248,9 +250,15 @@ export function stringifyInfo(value, optionsOrReplacer, space) {
: 1 + valueLength; // {} or [] + commas

if (space > 0 && valueLength > 0) {
bytes +=
(1 + stack.length * space) * valueLength + // for each key-value: \n{space}
1 + (stack.length - 1) * space; // for }
spaceBytes +=
// a space between ":" and a value for each object entry
(Array.isArray(value) ? 0 : valueLength) +
// the formula results from folding the following components:
// - for each key-value or element: ident + newline
// (1 + stack.length * space) * valueLength
// - ident (one space less) before "}" or "]" + newline
// (stack.length - 1) * space + 1
(1 + stack.length * space) * (valueLength + 1) - space;
}

stack.pop();
Expand Down
9 changes: 8 additions & 1 deletion src/stringify-info.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ function createInfoTest(value, ...args) {

it(title.replace(/[\u0000-\u001f\u0100-\uffff]/g, m => '\\u' + m.charCodeAt().toString(16).padStart(4, '0')), () => {
const native = String(wellformedStringify(value, ...args));
const nonFormatted = args[1] ? String(wellformedStringify(value, args[0])) : native;
const info = stringifyInfo(value, ...args);
const bytes = strBytesLength(native);
const spaceBytes = nonFormatted !== native
? bytes - strBytesLength(nonFormatted)
: 0;

assert.deepStrictEqual(info, {
bytes: strBytesLength(native),
bytes,
spaceBytes,
circular: []
});
});
Expand Down Expand Up @@ -61,6 +67,7 @@ describe('stringifyInfo()', () => {

assert.deepStrictEqual(actual, {
bytes: 18,
spaceBytes: 7,
circular: []
});
});
Expand Down

0 comments on commit 835a9ba

Please sign in to comment.