UNPKG

keys-mapper

Version:

keys-mapper 是一个通过设置属性名字映射,就可将一个对象转换成另一个对象的工具;支持循环引用、反向映射、深度映射

189 lines (184 loc) 6.26 kB
/* keys-mapper v2.0.0 author: { "name": "郭斌勇", "email": "guobinyong@qq.com" } license: MIT homepage: https://github.com/GuoBinyong/keys-mapper#readme repository: { "type": "git", "url": "https://github.com/GuoBinyong/keys-mapper" } description: keys-mapper 是一个通过设置属性名字映射,就可将一个对象转换成另一个对象的工具;支持循环引用、反向映射、深度映射 */ import { Decide } from 'com-tools'; /** * 将 KeyMaps 类型 转为 KeyMapsObject 类型 * @param keyMaps * @returns */ function toKeyMapsObject(keyMaps) { if (!Array.isArray(keyMaps)) { return keyMaps; } const entries = []; for (const [sourceKeys, mapKeys] of keyMaps) { if (Array.isArray(sourceKeys)) { const flatKeyMapArr = sourceKeys.map(function (key) { return [key, mapKeys]; }); Array.prototype.push.apply(entries, flatKeyMapArr); } else { entries.push([sourceKeys, mapKeys]); } } return Object.fromEntries(entries); } /** * 将 keyMaps1 和 keyMaps2 合并成一个 KeyMapsObject 对象 */ function mergeKeyMaps(keyMaps1, keyMaps2) { const kmo1 = toKeyMapsObject(keyMaps1); const kmo2 = toKeyMapsObject(keyMaps2); const entries = []; for (const [sourceKeys, mapKeys2] of Object.entries(kmo2)) { const mapKeys1 = kmo1[sourceKeys]; let mapKeys = Array.isArray(mapKeys2) ? [...mapKeys2] : [mapKeys2]; if (mapKeys1 !== undefined) { mapKeys = mapKeys.concat(mapKeys1); } entries.push([sourceKeys, mapKeys]); } return Object.fromEntries(entries); } /** * 将 keyMaps 反转 * @param keyMaps * @returns */ function reverseKeyMaps(keyMaps) { const keyMapsArr = Array.isArray(keyMaps) ? keyMaps : Object.entries(keyMaps); const reverseKMA = []; for (const [sourceKeys, mapKeys] of keyMapsArr) { const mapKeyArr = Array.isArray(mapKeys) ? mapKeys : [mapKeys]; const finalMKA = mapKeyArr.filter(function (key) { return key != null; }); reverseKMA.push([finalMKA, sourceKeys]); } return reverseKMA; } /** * key映射的核心函数 * @param options * @returns */ function keysMapperByRecursive(options) { const { source, keyMaps, maxDepth, startDepth, deleOther, keep, rawCopyMap, completeCB: complete, array: hasArray } = options; const completeCB = complete || function () { }; if (maxDepth < startDepth || !(source && typeof source === "object")) { completeCB(source); return source; } let decide = rawCopyMap.get(source); if (decide) { decide.then(completeCB); return decide.value; } decide = new Decide(); decide.then(completeCB); rawCopyMap.set(source, decide); const nextDepth = startDepth + 1; const newEntries = []; let entries; const isArray = Array.isArray(source); const target = isArray ? [] : {}; if (isArray) { if (!hasArray) { source.forEach(function (value, index) { target.push(undefined); keysMapperByRecursive(Object.assign(Object.assign({}, options), { source: value, startDepth: nextDepth, completeCB: function (newValue) { target.splice(index, 1, newValue); } })); }); decide.value = target; return target; } entries = source.map(function (item, index) { return [index, item]; }); } else { entries = Object.entries(source); } for (const [key, value] of entries) { const newKeys = keyMaps[key]; const newMapKeyArr = Array.isArray(newKeys) ? [...newKeys] : [newKeys]; const newKeyArr = newMapKeyArr.filter(k => k != null); if (newKeys === null || (newKeys === undefined && deleOther) || (newKeys !== undefined && !keep && newKeyArr.length === 0)) { continue; } keysMapperByRecursive(Object.assign(Object.assign({}, options), { source: value, startDepth: nextDepth, completeCB: function (newValue) { if (newKeys === undefined || keep) { newKeyArr.push(key); } newKeyArr.forEach(function (newKey) { newEntries.push([newKey, newValue]); }); } })); } for (const [key, value] of newEntries) { target[key] = value; } decide.value = target; return target; } /** * 创建以 presetKeyMapsObject 为预设的 keysMapper() 函数 * @param presetKeyMapsObject * @returns */ function createKeysMapper(presetKeyMapsObject) { function keysMapper(source, options, keyMaps) { if (options) { var { maxDepth, reverse } = options; } const maxDepth_Num = maxDepth == null ? Infinity : maxDepth; const presetKMO = keysMapper.presetKeyMapsObject; let finalKMO = presetKMO; if (keyMaps) { if (Object.keys(presetKMO).length > 0) { finalKMO = mergeKeyMaps(presetKMO, keyMaps); } else { finalKMO = toKeyMapsObject(keyMaps); } } if (reverse) { const reverseKMA = reverseKeyMaps(finalKMO); finalKMO = toKeyMapsObject(reverseKMA); } return keysMapperByRecursive(Object.assign(Object.assign({}, options), { source, keyMaps: finalKMO, maxDepth: maxDepth_Num, startDepth: 0, rawCopyMap: new Map() })); } Object.defineProperty(keysMapper, "presetKeyMapsObject", { configurable: true, enumerable: true, get: function () { if (!this._presetKeyMapsObject) { this._presetKeyMapsObject = {}; } return this._presetKeyMapsObject; }, set: function (newValue) { this._presetKeyMapsObject = newValue; } }); if (presetKeyMapsObject) { keysMapper.presetKeyMapsObject = presetKeyMapsObject; } return keysMapper; } const keysMapper = createKeysMapper(); export { createKeysMapper, keysMapper, mergeKeyMaps, reverseKeyMaps, toKeyMapsObject };