Skip to content

feat(preferred): add object-identity as an object-hash replacement#749

Closed
maraisr wants to merge 4 commits into
e18e:mainfrom
maraisr:maraisr/object-hash-identity-docs
Closed

feat(preferred): add object-identity as an object-hash replacement#749
maraisr wants to merge 4 commits into
e18e:mainfrom
maraisr:maraisr/object-hash-identity-docs

Conversation

@maraisr

@maraisr maraisr commented Jun 24, 2026

Copy link
Copy Markdown

🔗 Linked issue

There isn't a dedicated open issue for this one, it builds on the existing object-hash replacement page (prior context in #245). Happy to open a tracking issue first if you'd rather discuss it there.

📚 Description

This PR suggests object-identity as another replacement option for object-hash.

  • adds object-identity to the object-hash mapping in preferred.json (as a documented replacement, alongside ohash), and
  • updates the examples to use it as the stable serializer.

Full disclosure: I'm the author of object-identity, so please take this as you will. I've tried to keep every claim backed by numbers and to be honest about the trade-offs, very happy to adjust or drop anything.

Why it fits here

object-identity canonicalizes any value into a stable identity string, exactly the lib you reach for when you need a deterministic key to hash or to compare. It's deep and cycle-safe by default, and it's tiny.

Smaller — both are zero-dependency; minified + gzipped:

package min + gzip
object-identity ~555 B
safe-stable-stringify ~2.47 KB

That's roughly 4.5× smaller.

Faster — I am using my benchmarks for these two libraries (ops/sec, higher is better):

workload object-identity safe-stable-stringify
simple 910,961 593,432
deep 115,162 73,438
deep circular 175,990 138,163
big 7,095 7,377
leafy 43,393 20,510

So it's ahead on most cases (≈1.3×–2.1×) and about line-ball on the wide "big" object, where safe-stable-stringify is marginally quicker (room for improvement).

I took heavy inspiration from safe-stable-stringify's test-suite, and pass all of them for their default configuration. So this is very much a drop-in replacement.

Trade-offs / what it doesn't do

object-identity is deliberately opinionated: it always produces a canonical, cycle-safe identity and exposes no options, so it doesn't cover some of safe-stable-stringify's options, for example:

  • a custom key comparator / toggling deterministic
  • customising the circular-reference value (or throwing on cycles)
  • maximumDepth / maximumBreadth limits
  • a replacer, indentation / pretty-printing, and BigInt handling

It also emits an internal identity string rather than valid, human-readable JSON. In practice, for what this utility is usually used for, is for deriving a stable key to feed a hash, or checking structural equality. None of those tend to matter; you just want the same input to map to the same output. If you specifically need canonical JSON out, a replacer, or pretty output, safe-stable-stringify remains the better tool, which is why it stays alongside.

Very open to feedback, and happy to reword, or keep this docs-only and drop the manifest entry if that sits better with how you'd like to position it. Thanks for considering it, and for maintaining this ❤️

Add object-identity alongside safe-stable-stringify in the serializer suggestions, as well as switch examples to it.
@maraisr maraisr marked this pull request as draft June 24, 2026 08:09
@maraisr maraisr force-pushed the maraisr/object-hash-identity-docs branch from 92645d0 to 30f3b92 Compare June 24, 2026 08:20
@maraisr maraisr marked this pull request as ready for review June 24, 2026 08:31
Comment thread docs/modules/object-hash.md Outdated
@maraisr maraisr force-pushed the maraisr/object-hash-identity-docs branch from ca13f41 to aa9d12e Compare June 25, 2026 02:10

@dreyfus92 dreyfus92 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @maraisr thanks for this, and for the honest write-up of the trade-offs & the disclosure are appreciated.

happy to take it as a documented option, but a few changes first:

  • revert the safe-stable-stringify swaps in the web crypto + bun examples. the pr says it "stays alongside" but the diff removes it; let's leave those examples on safe-stable-stringify and let object-identity stand on its own section.
  • order it after ohash in the object-hash replacements array. this isn't cosmetic: the cli picks the first compatible entry, so prepending it makes object-identity the surfaced recommendation over ohash, and replacements.fyi renders the array in order so it'd also be top-listed there. given ohash is the maintained successor at ~1000x the adoption, it should lead.

worth flagging for transparency that object-identity is ~6.5k/week vs our ~10k soft bar, so i'm taking it as documented-but-not-leading rather than promoting it ahead of ohash.

also i'd love @43081j's input before merging this one.

@maraisr maraisr closed this Jun 25, 2026
@maraisr maraisr deleted the maraisr/object-hash-identity-docs branch June 25, 2026 02:21
@maraisr

maraisr commented Jun 25, 2026

Copy link
Copy Markdown
Author

Thank you for your review here @dreyfus92, and do apologise for any inconvenience this may have caused you. Maybe another time!

@43081j

43081j commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Very happy to add this once you see some adoption 👍

Please do recreate this PR then as it would be nice to include it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants