json-object-merge
Version:
Merge JSON Object using rules
127 lines (126 loc) • 5.55 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JSONObjectMerge = void 0;
var tslib_1 = require("tslib");
/* eslint-disable import/no-named-as-default-member */
var jsonpath_1 = tslib_1.__importDefault(require("jsonpath"));
var lodash_1 = require("lodash");
var JSONObjectMerge = function (target, source, rules, report) {
if (rules === void 0) { rules = {}; }
if (report === void 0) { report = false; }
var pathToOperationMap = {};
for (var jsonPathExpression in rules) {
var _paths = jsonpath_1.default.paths(target, jsonPathExpression);
for (var _i = 0, _paths_1 = _paths; _i < _paths_1.length; _i++) {
var pathComponents = _paths_1[_i];
pathComponents.shift();
pathComponents.unshift("$", "data");
pathToOperationMap[jsonpath_1.default.stringify(pathComponents)] =
rules[jsonPathExpression];
}
}
var result = { data: (0, lodash_1.cloneDeep)(target) };
var sourceObj = { data: (0, lodash_1.cloneDeep)(source) };
var updatedPaths = [];
var pathQueue = [["$", "data"]];
while (pathQueue.length > 0) {
var currentPath = pathQueue.shift();
var currentPathStr = jsonpath_1.default.stringify(currentPath);
var currentValue = jsonpath_1.default.value(result, currentPathStr);
var currentValueFromSource = jsonpath_1.default.value(sourceObj, currentPathStr);
var replace = false;
if ((0, lodash_1.isArray)(currentValue)) {
var operation = (0, lodash_1.isArray)(currentValueFromSource)
? pathToOperationMap[currentPathStr] || "COMBINE"
: "REPLACE";
switch (operation) {
case "REPLACE":
replace = true;
break;
case "APPEND":
if (report) {
updatedPaths.push({
path: currentPath,
operation: "APPEND",
count: currentValueFromSource.length
});
}
currentValue.push.apply(currentValue, currentValueFromSource);
break;
case "PREPEND":
if (report) {
updatedPaths.push({
path: currentPath,
operation: "PREPEND",
count: currentValueFromSource.length
});
}
currentValue.unshift.apply(currentValue, currentValueFromSource);
break;
default:
for (var i = 0; i < currentValue.length; i++) {
pathQueue.push(tslib_1.__spreadArray(tslib_1.__spreadArray([], currentPath, true), [i], false));
}
for (var i = currentValue.length; i < currentValueFromSource.length; i++) {
currentValue.push(currentValueFromSource[i]);
if (report) {
updatedPaths.push({
path: tslib_1.__spreadArray(tslib_1.__spreadArray([], currentPath, true), [i], false),
operation: "COMBINE"
});
}
}
}
}
else if ((0, lodash_1.isPlainObject)(currentValue)) {
var operation = (0, lodash_1.isPlainObject)(currentValueFromSource)
? pathToOperationMap[currentPathStr] || "COMBINE"
: "REPLACE";
switch (operation) {
case "REPLACE":
replace = true;
break;
default:
for (var property in currentValue) {
pathQueue.push(tslib_1.__spreadArray(tslib_1.__spreadArray([], currentPath, true), [property], false));
}
for (var property in currentValueFromSource) {
if (currentValue[property] === undefined) {
currentValue[property] = currentValueFromSource[property];
if (report) {
updatedPaths.push({
path: tslib_1.__spreadArray(tslib_1.__spreadArray([], currentPath, true), [property], false),
operation: "COMBINE"
});
}
}
}
}
}
else {
replace = true;
}
if (replace && currentValueFromSource !== undefined) {
jsonpath_1.default.value(result, currentPathStr, currentValueFromSource);
if (report) {
updatedPaths.push({
path: tslib_1.__spreadArray([], currentPath, true),
operation: "REPLACE"
});
}
}
}
if (report) {
return {
merged: result.data,
report: {
updatedPaths: updatedPaths.map(function (updatedPath) {
updatedPath.path = tslib_1.__spreadArray(["$"], updatedPath.path.slice(2), true);
return updatedPath;
})
}
};
}
return result.data;
};
exports.JSONObjectMerge = JSONObjectMerge;