From 26dc0008c4bfc8e1b5268cdaa33143e9ecf0436f Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 19 Mar 2023 18:25:42 +0100 Subject: [PATCH] fix: toJSON function receiving array keys as number instead of string --- CHANGELOG.md | 1 + index.js | 12 ++++++------ test.js | 26 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29d3df9..abb770b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v2.4.3 +- Fixed toJSON function receiving array keys as number instead of string - Fixed replacer function receiving array keys as number instead of string - Fixed replacer function not being called for TypedArray entries - Improved performance to escape long strings that contain characters that need escaping diff --git a/index.js b/index.js index 71b5efd..707daa0 100644 --- a/index.js +++ b/index.js @@ -322,11 +322,11 @@ function configure (options) { const maximumValuesToStringify = Math.min(value.length, maximumBreadth) let i = 0 for (; i < maximumValuesToStringify - 1; i++) { - const tmp = stringifyArrayReplacer(i, value[i], stack, replacer, spacer, indentation) + const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation) res += tmp !== undefined ? tmp : 'null' res += join } - const tmp = stringifyArrayReplacer(i, value[i], stack, replacer, spacer, indentation) + const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation) res += tmp !== undefined ? tmp : 'null' if (value.length - 1 > maximumBreadth) { const removedKeys = value.length - maximumBreadth - 1 @@ -412,11 +412,11 @@ function configure (options) { const maximumValuesToStringify = Math.min(value.length, maximumBreadth) let i = 0 for (; i < maximumValuesToStringify - 1; i++) { - const tmp = stringifyIndent(i, value[i], stack, spacer, indentation) + const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation) res += tmp !== undefined ? tmp : 'null' res += join } - const tmp = stringifyIndent(i, value[i], stack, spacer, indentation) + const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation) res += tmp !== undefined ? tmp : 'null' if (value.length - 1 > maximumBreadth) { const removedKeys = value.length - maximumBreadth - 1 @@ -520,11 +520,11 @@ function configure (options) { const maximumValuesToStringify = Math.min(value.length, maximumBreadth) let i = 0 for (; i < maximumValuesToStringify - 1; i++) { - const tmp = stringifySimple(i, value[i], stack) + const tmp = stringifySimple(String(i), value[i], stack) res += tmp !== undefined ? tmp : 'null' res += ',' } - const tmp = stringifySimple(i, value[i], stack) + const tmp = stringifySimple(String(i), value[i], stack) res += tmp !== undefined ? tmp : 'null' if (value.length - 1 > maximumBreadth) { const removedKeys = value.length - maximumBreadth - 1 diff --git a/test.js b/test.js index 7c95e90..91681e6 100644 --- a/test.js +++ b/test.js @@ -2,6 +2,32 @@ const { test } = require('tap') const { stringify } = require('./index.js') const clone = require('clone') +test('toJSON receives array keys as string', function (assert) { + const object = [{ + toJSON (key) { + assert.equal(key, '0') + return 42 + } + }] + + const expected = JSON.stringify(object) + + let actual = stringify(object) + assert.equal(actual, expected) + + actual = stringify(object, ['0']) + assert.equal(actual, expected) + + // @ts-expect-error + actual = stringify(object, (key, value) => value) + assert.equal(actual, expected) + + actual = stringify(object, null, 2) + assert.equal(actual, '[\n 42\n]') + + assert.end() +}) + test('circular reference to root', function (assert) { const fixture = { name: 'Tywin Lannister' } fixture.circle = fixture