smart-json-diff
Version:
A modern, compact JSON comparison library with path-aware output and multiple output modes
67 lines (66 loc) • 2.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.smartJsonDiff = smartJsonDiff;
const utils_1 = require("./utils");
function smartJsonDiff(a, b, options = {}) {
const { output = 'array', onChange, filterPath, compareArraysByIndex = true, strict = true } = options;
const results = [];
function compare(objA, objB, path = '') {
if (strict ? objA === objB : objA == objB) {
return;
}
if (objA === null || objB === null || objA === undefined || objB === undefined) {
if (objA !== objB) {
if (!filterPath || filterPath(path)) {
results.push({ path, old: objA, new: objB });
}
}
return;
}
if (typeof objA === 'function' || typeof objB === 'function' || typeof objA === 'symbol' || typeof objB === 'symbol') {
return;
}
if (typeof objA !== typeof objB) {
if (!filterPath || filterPath(path)) {
results.push({ path, old: objA, new: objB });
}
return;
}
if ((0, utils_1.isObject)(objA) && (0, utils_1.isObject)(objB)) {
const allKeys = new Set([...Object.keys(objA), ...Object.keys(objB)]);
for (const key of allKeys) {
const newPath = path ? `${path}.${key}` : key;
compare(objA[key], objB[key], newPath);
}
}
else if (Array.isArray(objA) && Array.isArray(objB)) {
if (compareArraysByIndex) {
const maxLength = Math.max(objA.length, objB.length);
for (let i = 0; i < maxLength; i++) {
const newPath = `${path}[${i}]`;
compare(objA[i], objB[i], newPath);
}
}
}
else if (objA !== objB) {
if (!filterPath || filterPath(path)) {
results.push({ path, old: objA, new: objB });
}
}
}
compare(a, b);
if (output === 'callback' && onChange) {
results.forEach(({ path, old, new: newVal }) => {
onChange(path, old, newVal);
});
return;
}
if (output === 'object') {
const objectResult = {};
results.forEach(({ path, old, new: newVal }) => {
objectResult[path] = { old, new: newVal };
});
return objectResult;
}
return results;
}