Last active
January 5, 2023 17:55
-
-
Save scottoffen/ceb9bef7e9537b1dcaf1f2b22b9abb74 to your computer and use it in GitHub Desktop.
Deep compare two objects and return a list of discrepencies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const deepDiff = (local, remote, prefix = "") => { | |
let diff = []; | |
if (local === null && remote === null) return diff; | |
if (local === null || remote === null) { | |
let lnull = (local === null) ? "null" : typeof (local); | |
let rnull = (remote === null) ? "null" : typeof (remote); | |
diff.push(`${prefix} (null): local is ${lnull} and remote is ${rnull}`); | |
return diff; | |
} | |
let type1 = typeof (local); | |
let type2 = typeof (remote); | |
if (type1 !== type2) { | |
diff.push(`${prefix} (type): local is ${type1} and remote is ${type2}`); | |
return diff; | |
} | |
if (type1 === "object") { | |
let localIsArray = Array.isArray(local); | |
let remoteIsArray = Array.isArray(remote); | |
if (localIsArray !== remoteIsArray) { | |
diff.push(`${prefix} (type): local is array ${localIsArray} and remote is array ${remoteIsArray}`); | |
return diff; | |
} | |
if (localIsArray) { | |
if (local.length !== remote.length) { | |
diff.push(`${prefix} (length): local has ${local.length} elements and remote has ${remote.length} elements`); | |
} | |
else { | |
for (let i = 0; i < local.length; i++) { | |
diff = diff.concat(deepDiff(local[i], remote[i], `${prefix}[${i}]`)) | |
} | |
} | |
return diff; | |
} else { | |
let props = []; | |
prefix += (prefix.length > 0) ? "." : ""; | |
for (const [key, actual] of Object.entries(local)) { | |
props.push(key); | |
if (!(key in remote)) { | |
diff.push(`${prefix}${key} (missing): remote does not contain this key`); | |
continue; | |
} | |
let expected = remote[key]; | |
diff = diff.concat(deepDiff(actual, expected, `${prefix}${key}`)); | |
} | |
for (const key of Object.keys(remote)) { | |
if (props.includes(key)) continue; | |
diff.push(`${prefix}${key} (missing): local does not contain this key`); | |
} | |
} | |
} | |
else if (local !== remote) { | |
diff.push(`${prefix} (value): local is ${local} and remote is ${remote}`); | |
return diff; | |
} | |
return diff; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment