UNPKG

json-object-merge

Version:
123 lines (122 loc) 5.14 kB
import { __spreadArray } from "tslib"; /* eslint-disable import/no-named-as-default-member */ import jp from "jsonpath"; import { cloneDeep, isArray, isPlainObject } from "lodash"; export 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 = jp.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[jp.stringify(pathComponents)] = rules[jsonPathExpression]; } } var result = { data: cloneDeep(target) }; var sourceObj = { data: cloneDeep(source) }; var updatedPaths = []; var pathQueue = [["$", "data"]]; while (pathQueue.length > 0) { var currentPath = pathQueue.shift(); var currentPathStr = jp.stringify(currentPath); var currentValue = jp.value(result, currentPathStr); var currentValueFromSource = jp.value(sourceObj, currentPathStr); var replace = false; if (isArray(currentValue)) { var operation = 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(__spreadArray(__spreadArray([], currentPath, true), [i], false)); } for (var i = currentValue.length; i < currentValueFromSource.length; i++) { currentValue.push(currentValueFromSource[i]); if (report) { updatedPaths.push({ path: __spreadArray(__spreadArray([], currentPath, true), [i], false), operation: "COMBINE" }); } } } } else if (isPlainObject(currentValue)) { var operation = isPlainObject(currentValueFromSource) ? pathToOperationMap[currentPathStr] || "COMBINE" : "REPLACE"; switch (operation) { case "REPLACE": replace = true; break; default: for (var property in currentValue) { pathQueue.push(__spreadArray(__spreadArray([], currentPath, true), [property], false)); } for (var property in currentValueFromSource) { if (currentValue[property] === undefined) { currentValue[property] = currentValueFromSource[property]; if (report) { updatedPaths.push({ path: __spreadArray(__spreadArray([], currentPath, true), [property], false), operation: "COMBINE" }); } } } } } else { replace = true; } if (replace && currentValueFromSource !== undefined) { jp.value(result, currentPathStr, currentValueFromSource); if (report) { updatedPaths.push({ path: __spreadArray([], currentPath, true), operation: "REPLACE" }); } } } if (report) { return { merged: result.data, report: { updatedPaths: updatedPaths.map(function (updatedPath) { updatedPath.path = __spreadArray(["$"], updatedPath.path.slice(2), true); return updatedPath; }) } }; } return result.data; };