JSON.prune icon indicating copy to clipboard operation
JSON.prune copied to clipboard

Cannot distinguish between [Circular] and [MaxDepth] in replacer

Open Adi1231234 opened this issue 5 months ago • 3 comments

Hi, first of all thanks for maintaining this project 🙏

While using json-prune with a custom replacer, I noticed that there’s no way to tell the difference between a real circular reference and a node that was pruned because maxDepth was reached.

Looking at the source:

if (depthDecr <= 0 || seen.indexOf(value) !== -1) {
  if (replacer) {
    var replacement = replacer(value, prunedString, true);
    return replacement === undefined ? undefined : '' + replacement;
  }
  return prunedString;
}

The third argument to replacer is always true for both conditions. This makes it impossible to produce different placeholders, e.g.:

  • [Circular] for repeated references
  • [MaxDepth] for values beyond the configured depth

Expected behavior:

The library should provide enough context to replacer to differentiate the two cases. For example:

  • Pass a fourth parameter reason ('circular' | 'depth')
  • Or change the boolean flag so it’s true only for circular references, and something else for depth.

Proposal:

Would it be possible to adjust the implementation to:

if (depthDecr <= 0) {
  if (replacer) return replacer(value, prunedString, false, 'depth');
  return prunedString;
}
if (seen.indexOf(value) !== -1) {
  if (replacer) return replacer(value, prunedString, true, 'circular');
  return prunedString;
}

This would be backward-compatible (the old boolean parameter still works), but gives users the ability to distinguish between circular references and max-depth pruning.

Adi1231234 avatar Aug 24 '25 14:08 Adi1231234