Compare JSON object properties for new/changed/deleted
(_ => { function filterUnique() { const keys = new Set(); return (key) => !keys.has(key) ? keys.add(key) || true : false; } function* fullOuterJoin(left, right, keyFn, selectFn) { const leftLookup = {}; const rightLookup = {}; left.forEach(x => leftLookup[keyFn(x)] = x); right.forEach(x => rightLookup[keyFn(x)] = x); const unique = filterUnique(); const keys = [...left.map(x => keyFn(x)), ...right.map(x => keyFn(x))].filter(unique); for (const key of keys) { const l = leftLookup[key]; const r = rightLookup[key]; yield selectFn(l, r, key); } } function flattenObject(obj) { const result = {}; for (const [k, v] of Object.entries(obj)) { if (typeof v === "object" && v) { for (const [x, y] of Object.entries(flattenObject(v))) { result[k + "." + x] = y; } continue; } result[k] = v; } return result; } const mapkv = x => ({key: x[0], value: x[1]}); const left = Object.entries(flattenObject(nl)).map(mapkv); const right = Object.entries(flattenObject(en)).map(mapkv); const changes = Array.from(fullOuterJoin(left, right, a => a.key, (l, r, k) => ({ l, r, key: k }))).filter(x => !x.l || !x.r); console.table(changes.map(x => ({ key: x.key, left: x.l?.value, right: x.r?.value }))); })();
const getNew = (oldList: any[], newList: any[], equals: Function) => newList.filter(i => !oldList.some(o => equals(o, i))); const getChanged = (oldList: any[], newList: any[], equals: Function, changed: Function) => { return newList.reduce((arr, curr) => { const old = oldList.filter(o => equals(o, curr))[0]; if (old && changed(curr, old)) { arr.push({ key: curr.key, oldvalue: old.value, value: curr.value }); } return arr; }, []); }; const getUnchanged = (oldList: any[], newList: any[], equals: Function, changed: Function) => { return newList.reduce((arr, curr) => { const old = oldList.filter(o => equals(o, curr))[0]; if (!(old && changed(curr, old))) { arr.push({ key: curr.key, value: curr.value }); } return arr; }, []); }; // deleted items is just the lists reversed const getDeleted = (oldList: any[], newList: any[], equals) => getNew(newList, oldList, equals); const flattenObject = (obj: object): any => { const result = {}; for (const [k, v] of Object.entries(obj)) { if (typeof v === "object" && v) { const flatObject = flattenObject(v); for (const [x, y] of Object.entries(flatObject)) { result[k + "." + x] = y; } } else { result[k] = v; } } return result; }; const mapkv = x => ({key: x[0], value: x[1]}); const currentJsonValues = JSON.parse(currentVersion.entityValueJson); const previousJsonValues = JSON.parse(previousVersion.entityValueJson); const currentEntries = Object.entries(flattenObject(currentJsonValues)).map(mapkv); const previousEntries = Object.entries(flattenObject(previousJsonValues)).map(mapkv); const equal = (a, b) => a.key === b.key; const changed = (a, b) => a.value !== b.value; const addedProps = getNew(previousEntries, currentEntries, equal); const changedProps = getChanged(previousEntries, currentEntries, equal, changed); const deletedProps = getDeleted(previousEntries, currentEntries, equal); const unchangedProps = getUnchanged(previousEntries, currentEntries, equal, changed);
218800cookie-checkGet object diff