UNPKG

json-treeify

Version:

json-treeify: Get tree string(├└│─) via json, support browser|node, browser none dependencies!

96 lines (94 loc) 3.69 kB
let {getTypeOf, isObject, isFunction, isString, isSpreadable, isNill} = require('./type-of'); /** * 递归遍历一个json * @param {Object} json * @param {Function} cb callback(key,val,curKeyPath,typeStr,isComplexObj,curDepth,isCircular) and context is parent obj * @param {string} rootAlias * @param {Boolean} safeMode default is true * @returns {Array} keysArr */ function travelJson(json, cb, rootAlias, safeMode){ if(!isObject(json)){ throw new TypeError('The first param should be an Object instance!'); } // 安全模式 safeMode = safeMode === undefined ? true : safeMode; let safeStack = [];//记录safe检查时候的对象 let safeKeys = []; //记录safe检查时候的key值 // res let keysArr = []; let needCb = isFunction(cb); rootAlias = (isString(rootAlias) ? rootAlias : '') || 'ROOT'; // loop function travel(obj, curKeyPath, depth, cb){ if(!isNill(obj)){ // safeMode if(safeMode){ let objIndex = safeStack.indexOf(obj); if(~objIndex){// if found it safeStack.splice(objIndex + 1);// delete all before it safeKeys.splice(objIndex + 1);// delete all before it }else{ safeStack.push(obj);// push safeKeys.push(curKeyPath); } } // loop let keys = Object.keys(obj); const lastIndex = keys.length - 1; keys.forEach((k, i) => { let isFirstChild = i === 0; let isLastChild = i === lastIndex; //这里即使curKeyPath为空字符串""也请加上".",这样做是为了统一的循环次数,不管rootAlias是否为空字符串"" let newKeyPath = `${curKeyPath}.${k}`; keysArr.push(`${newKeyPath}`);//push a new string // 记录下层级 let curDepth = depth + 1; // 值 let v = obj[k]; let isCircular = false; // safeMode if(safeMode){ let kIndex = safeStack.indexOf(v); if(~kIndex){// Circular isCircular = true; v = `[Circular->${safeKeys[kIndex]}]`; }else{ isCircular = false; v = obj[k]; } } // 是否可以再展开,这里,函数被视为不可再展开 let spreadable = isSpreadable(v) && !isFunction(v); // do sth in callback... // needCb && cb.call(obj, k, v, `${newKeyPath}`, getTypeOf(v), spreadable, curDepth, isCircular, isFirstChild, isLastChild); needCb && cb.call(obj, k, v, { keyPath: `${newKeyPath}`, depth: curDepth, type: getTypeOf(v), isCircular, isSpreadable: spreadable, isFirst: isFirstChild, isLast: isLastChild }); // then travel in deep if(spreadable){ travel(v, newKeyPath, curDepth, cb); } }); } } // do on catch mode try{ travel(json, rootAlias, 1, cb);// 栈溢出,递归次数导致内存超限 }catch(eTravel){ try{ JSON.stringify(json); }catch(eStringify){ throw eStringify; } throw eTravel; } return keysArr; } module.exports = travelJson;