Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Next

- Changed the default circular marker to `'[Circular: N]'`, where `N` is the referenced ancestor's depth, starting at 0 for the root.
Set `circularValue: '[Circular]'` to retain the previous format. This changes the serialized output for circular references.

- Added `'string'` as possible `bigint` option value. Bigint values are serialized as JSON strings using it.

```js
Expand Down Expand Up @@ -156,4 +159,4 @@ configure({ circularValue: undefined })(object)
- Fix typescript definition (https://github.com/BridgeAR/safe-stable-stringify/commit/7a87478)
- Improve code coverage (https://github.com/BridgeAR/safe-stable-stringify/commit/ed8cadc, https://github.com/BridgeAR/safe-stable-stringify/commit/b58c494)
- Update dev dependencies (https://github.com/BridgeAR/safe-stable-stringify/commit/b857ea8)
- Improve docs
- Improve docs
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export function stringify(value: unknown, replacer?: ((key: string, value: unkno

export interface StringifyOptions {
bigint?: boolean | 'string',
/** Defaults to '[Circular: N]', where N is the ancestor depth, starting at 0 for the root. */
circularValue?: string | null | TypeErrorConstructor | ErrorConstructor,
deterministic?: boolean | ((a: string, b: string) => number),
maximumBreadth?: number,
Expand Down
28 changes: 19 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ function stringifyTypedArray (array, separator, maximumBreadth, bigint) {
return res
}

/** @param {number} index */
function stringifyCircularDepth (index) {
return `"[Circular: ${index}]"`
}

/** @param {Record<string, unknown>} options */
function getCircularValueOption (options) {
if (hasOwnProperty.call(options, 'circularValue')) {
const circularValue = options.circularValue
Expand All @@ -103,7 +109,7 @@ function getCircularValueOption (options) {
}
throw new TypeError('The "circularValue" argument must be of type string or the value null or undefined')
}
return '"[Circular]"'
return stringifyCircularDepth
}

function getDeterministicOption (options) {
Expand Down Expand Up @@ -268,8 +274,9 @@ function configure (options) {
if (value === null) {
return 'null'
}
if (stack.indexOf(value) !== -1) {
return circularValue
const circularIndex = stack.indexOf(value)
if (circularIndex !== -1) {
return typeof circularValue === 'function' ? circularValue(circularIndex) : circularValue
}

let res = ''
Expand Down Expand Up @@ -379,8 +386,9 @@ function configure (options) {
if (value === null) {
return 'null'
}
if (stack.indexOf(value) !== -1) {
return circularValue
const circularIndex = stack.indexOf(value)
if (circularIndex !== -1) {
return typeof circularValue === 'function' ? circularValue(circularIndex) : circularValue
}

const originalIndentation = indentation
Expand Down Expand Up @@ -480,8 +488,9 @@ function configure (options) {
return 'null'
}
}
if (stack.indexOf(value) !== -1) {
return circularValue
const circularIndex = stack.indexOf(value)
if (circularIndex !== -1) {
return typeof circularValue === 'function' ? circularValue(circularIndex) : circularValue
}
const originalIndentation = indentation

Expand Down Expand Up @@ -593,8 +602,9 @@ function configure (options) {
return 'null'
}
}
if (stack.indexOf(value) !== -1) {
return circularValue
const circularIndex = stack.indexOf(value)
if (circularIndex !== -1) {
return typeof circularValue === 'function' ? circularValue(circularIndex) : circularValue
}

let res = ''
Expand Down
9 changes: 6 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const circular = { b: 1, a: 0 }
circular.circular = circular

stringify(circular)
// '{"a":0,"b":1,"circular":"[Circular]"}'
// '{"a":0,"b":1,"circular":"[Circular: 0]"}'
JSON.stringify(circular)
// TypeError: Converting circular structure to JSON

Expand All @@ -50,7 +50,9 @@ stringify(circular, ['a', 'b'], 2)
* `circularValue` {string|null|undefined|ErrorConstructor} Defines the value for
circular references. Set to `undefined`, circular properties are not
serialized (array entries are replaced with `null`). Set to `Error`, to throw
on circular references. **Default:** `'[Circular]'`.
on circular references. **Default:** `'[Circular: N]'`, where `N` is the
referenced ancestor's depth, starting at 0 for the root. Set to `'[Circular]'`
to retain the previous default format.
* `deterministic` {boolean|function} If `true` or a `Array#sort(comparator)`
comparator method, guarantee a deterministic key order instead of relying on
the insertion order. **Default:** `true`.
Expand Down Expand Up @@ -113,7 +115,8 @@ throwOnCircular(circular);

## Differences to JSON.stringify

1. _Circular values_ are replaced with the string `[Circular]` (configurable).
1. _Circular values_ identify the referenced ancestor's depth as `[Circular: N]`
(configurable), starting at 0 for the root.
1. _Object keys_ are sorted instead of using the insertion order (configurable).
1. _BigInt_ values are stringified as regular number instead of throwing a
TypeError (configurable).
Expand Down
Loading
Loading