Skip to content

Instantly share code, notes, and snippets.

@scottoffen
Last active January 5, 2023 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottoffen/ceb9bef7e9537b1dcaf1f2b22b9abb74 to your computer and use it in GitHub Desktop.
Save scottoffen/ceb9bef7e9537b1dcaf1f2b22b9abb74 to your computer and use it in GitHub Desktop.
Deep compare two objects and return a list of discrepencies.
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