User Rating 0.0
Total Usage 0 times
Accepts valid JSON or JS object literals (no functions). Arrays are order-invariant.
Is this tool helpful?

Your feedback helps us improve.

About

Comparing two deeply nested JavaScript objects for structural equivalence is a non-trivial operation. A naive recursive equality check runs in O(n) time on every comparison and cannot be indexed or cached. This tool serializes any JSON-compatible object into a canonical form - sorting object keys lexicographically and normalizing array order - then computes the 128-bit MD5 digest per RFC 1321. The resulting 32-character hexadecimal string serves as a fingerprint: two objects produce identical hashes if and only if they are structurally equivalent (ignoring array element order). Objects containing function values at any depth are rejected, as functions lack a deterministic string representation.

The canonical serialization step is critical. Without it, {a:1, b:2} and {b:2, a:1} would produce different hashes despite logical equivalence. Similarly, arrays [1,2] and [2,1] are treated as identical sets. This makes the tool suitable for indexing object states in databases, cache invalidation keys, or regression test fixtures where insertion order is non-deterministic. The MD5 implementation here is pure JavaScript - no CryptoJS, no Underscore, no dependencies. Note: MD5 is not cryptographically secure for password hashing. It is used here strictly as a fast, compact fingerprint for equivalence testing.

md5 hash javascript object json to md5 object equivalence deep hash checksum

Formulas

The MD5 algorithm processes an input message in 512-bit blocks. Each block undergoes 64 operations organized into 4 rounds of 16 operations. The four auxiliary functions are:

F(B, C, D) = (B C) (¬B D)
G(B, C, D) = (B D) (C ¬D)
H(B, C, D) = B &xor; C &xor; D
I(B, C, D) = C &xor; (B ¬D)

Each round operation follows the pattern:

a = b + ((a + F(b,c,d) + Mk + Ti) s)

where Mk is the k-th 32-bit word of the message block, Ti = floor(232 × |sin(i)|) is the per-round constant, s is the per-round shift amount, and denotes left circular rotation. The initial hash values are a0 = 0x67452301, b0 = 0xEFCDAB89, c0 = 0x98BADCFE, d0 = 0x10325476.

The canonical serialization before hashing follows this logic: for an object, sort all keys alphabetically, recurse into each value, and concatenate as key:value pairs. For an array, recursively serialize each element, sort the serialized strings lexicographically, then join. This ensures both key-order invariance and array-order invariance.

Reference Data

Feature / BehaviorThis ToolNotes
Key order sensitivityOrder-invariantKeys sorted lexicographically at every depth
Array order sensitivityOrder-invariantElements sorted by canonical serialized form
Nested objectsFully recursiveNo depth limit
Nested arraysFully recursiveMixed types sorted by type then value
null valuesSupportedSerialized as null
undefined valuesOmittedMatches JSON.stringify behavior
function valuesRejectedError thrown with path to offending key
Boolean valuesSupportedTRUE1
Number precisionIEEE 754 double0.1 + 0.20.3
Empty object {}99914b932bd37a50b983c5e7c90ae93bMD5 of canonical {}
Empty array []d751713988987e9331980363e24189ceMD5 of canonical []
String encodingUTF-8Full Unicode support
Max safe integer9007199254740991Beyond this, precision loss may alter hash
Hash output length32 hex characters128 bits
Collision probability1 in 2128Sufficient for equivalence testing
AlgorithmMD5 (RFC 1321)Not suitable for cryptographic security
DependenciesNonePure vanilla JavaScript
Circular referencesRejectedError thrown to prevent infinite recursion
NaN valuesSerialized as nullMatches JSON.stringify behavior
Infinity valuesSerialized as nullMatches JSON.stringify behavior

Frequently Asked Questions

The canonical serialization step sorts array elements by their serialized string representation before hashing. This deliberate design choice treats arrays as unordered sets for equivalence testing. If your use case requires order-sensitive comparison, this tool is not appropriate - you would need a serializer that preserves insertion order.
JavaScript functions lack a standardized, deterministic string representation. Two functionally identical closures can have different source text due to minification, variable renaming, or environment capture. Including them would produce unreliable hashes. Strip all function properties before hashing, or serialize only the data subset of your object.
Circular references (e.g., obj.self = obj) cause infinite recursion during serialization. The tool maintains a visited-object set and throws an error with the path to the circular reference if one is detected. You must break the cycle before hashing.
No. MD5 has known collision vulnerabilities (Wang & Yu, 2004) and is considered broken for cryptographic purposes. This implementation is strictly for fast structural fingerprinting of data objects. For security-sensitive hashing, use SHA-256 or bcrypt.
JavaScript represents numbers as IEEE 754 double-precision floats. The expression 0.1 + 0.2 evaluates to 0.30000000000000004, not 0.3. These will produce different hashes. If precision matters, round your numbers or use string representations before hashing.
Yes. Keys and string values are serialized as UTF-8 before MD5 computation. The lexicographic sort uses JavaScript's default string comparison, which operates on UTF-16 code units. Keys like "é" and "e\u0301" (composed vs. decomposed) will produce different hashes. Normalize Unicode (NFC/NFD) before hashing if this matters.
Properties with undefined values are omitted from serialization, matching the behavior of JSON.stringify. This means {a: undefined} hashes identically to {}. In contrast, null is explicitly serialized as the string null and contributes to the hash.