@toolsycc/json-diff
Version:
A lightweight utility to compare, intersect or subtract JSON objects deeply.
85 lines (84 loc) • 2.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.diffJson = diffJson;
exports.intersectJson = intersectJson;
exports.subtractJson = subtractJson;
exports.isObject = isObject;
exports.isEqual = isEqual;
function diffJson(a, b) {
const added = {};
const removed = {};
const changed = {};
const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]);
for (const key of keys) {
const valA = a?.[key];
const valB = b?.[key];
if (!(key in a)) {
added[key] = valB;
}
else if (!(key in b)) {
removed[key] = valA;
}
else if (isObject(valA) && isObject(valB)) {
const sub = diffJson(valA, valB);
if (Object.keys(sub.added).length || Object.keys(sub.removed).length || Object.keys(sub.changed).length) {
changed[key] = [valA, valB];
}
}
else if (!isEqual(valA, valB)) {
changed[key] = [valA, valB];
}
}
return { added, removed, changed };
}
function intersectJson(a, b) {
if (!isObject(a) || !isObject(b))
return undefined;
const result = {};
for (const key in a) {
if (key in b) {
const valA = a[key];
const valB = b[key];
if (isObject(valA) && isObject(valB)) {
const sub = intersectJson(valA, valB);
if (sub && Object.keys(sub).length)
result[key] = sub;
}
else if (isEqual(valA, valB)) {
result[key] = valA;
}
}
}
return result;
}
function subtractJson(a, b) {
if (!isObject(a))
return a;
if (!isObject(b))
return a;
const result = {};
for (const key in a) {
if (!(key in b)) {
result[key] = a[key];
}
else {
const valA = a[key];
const valB = b[key];
if (isObject(valA) && isObject(valB)) {
const sub = subtractJson(valA, valB);
if (Object.keys(sub).length > 0)
result[key] = sub;
}
else if (!isEqual(valA, valB)) {
result[key] = valA;
}
}
}
return result;
}
function isObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function isEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}