Skip to content

Commit 835a9ba

Browse files
committed
Add spaceBytes field to stringifyInfo() result
1 parent 5dcb5c4 commit 835a9ba

File tree

4 files changed

+24
-7
lines changed

4 files changed

+24
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## next
22

3+
- 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
34
- Fixed `stringifyInfo()` to correctly accept the `space` parameter from options, i.e. `stringifyInfo(data, { space: 2 })`
45

56
## 0.6.1 (2024-08-06)

index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ declare module '@discoveryjs/json-ext' {
1717
}
1818
type StringifyInfoResult = {
1919
bytes: number;
20-
circular: Object[];
20+
spaceBytes: number;
21+
circular: object[];
2122
};
2223

2324
export function parseChunked(input: Iterable<Chunk> | AsyncIterable<Chunk>): Promise<any>;

src/stringify-info.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export function stringifyInfo(value, optionsOrReplacer, space) {
158158
const root = { '': value };
159159
let stop = false;
160160
let bytes = 0;
161+
let spaceBytes = 0;
161162
let objects = 0;
162163

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

170171
return {
171-
bytes: isNaN(bytes) ? Infinity : bytes,
172+
bytes: isNaN(bytes) ? Infinity : bytes + spaceBytes,
173+
spaceBytes,
172174
circular: [...circular]
173175
};
174176

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

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

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

250252
if (space > 0 && valueLength > 0) {
251-
bytes +=
252-
(1 + stack.length * space) * valueLength + // for each key-value: \n{space}
253-
1 + (stack.length - 1) * space; // for }
253+
spaceBytes +=
254+
// a space between ":" and a value for each object entry
255+
(Array.isArray(value) ? 0 : valueLength) +
256+
// the formula results from folding the following components:
257+
// - for each key-value or element: ident + newline
258+
// (1 + stack.length * space) * valueLength
259+
// - ident (one space less) before "}" or "]" + newline
260+
// (stack.length - 1) * space + 1
261+
(1 + stack.length * space) * (valueLength + 1) - space;
254262
}
255263

256264
stack.pop();

src/stringify-info.test.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ function createInfoTest(value, ...args) {
1919

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

2429
assert.deepStrictEqual(info, {
25-
bytes: strBytesLength(native),
30+
bytes,
31+
spaceBytes,
2632
circular: []
2733
});
2834
});
@@ -61,6 +67,7 @@ describe('stringifyInfo()', () => {
6167

6268
assert.deepStrictEqual(actual, {
6369
bytes: 18,
70+
spaceBytes: 7,
6471
circular: []
6572
});
6673
});

0 commit comments

Comments
 (0)