未知层级深层嵌套JSON遍历 按条件增删改键值对实现方案咨询
解决方案
核心实现逻辑
- 深度优先递归遍历JSON全树,自动覆盖所有嵌套的对象、数组节点,无需用户提前查询并传入目标路径
- 保留原有AND多条件匹配规则,节点满足所有传入的where条件即判定为匹配成功
- 完整支持新增/更新/删除三种操作,所有匹配节点会批量执行对应操作
- 内置文件读写逻辑,操作完成后自动将修改后的内容写回原JSON文件
完整实现代码
const _ = require("lodash"); const fs = require("fs"); const path = require("path"); const actions = ["add", "delete", "update"]; // 条件匹配工具:判断节点是否满足所有where条件 const isMatch = (node, where) => { if (!_.isObject(node) || _.isArray(node)) return false; return where.every(condition => { for (const [k, v] of Object.entries(condition)) { if (node[k] !== v) return false; } return true; }) } // 递归遍历树节点,执行匹配和操作 const traverseAndOperate = (node, where, data, action) => { // 处理数组:倒序遍历避免删除元素时索引错乱 if (_.isArray(node)) { for (let i = node.length - 1; i >= 0; i--) { const item = node[i]; // 先判断当前元素是否匹配条件 if (isMatch(item, where)) { switch(action) { case "add": case "update": node[i] = {...item, ...data}; break; case "delete": node.splice(i, 1); break; } } // 递归遍历子节点 traverseAndOperate(item, where, data, action); } return; } // 处理对象 if (_.isObject(node)) { // 先判断当前对象是否匹配条件 if (isMatch(node, where)) { switch(action) { case "add": case "update": Object.assign(node, data); break; case "delete": // 传入数组格式的data则删除匹配对象的对应键 if (_.isArray(data)) { data.forEach(key => delete node[key]); } break; } } // 递归遍历所有属性值 Object.values(node).forEach(val => traverseAndOperate(val, where, data, action)); } } const consumer = (filePath, where, data, action) => { try { const act = action.toLowerCase(); if (!actions.includes(act)) throw new Error("invalid action provided"); if (!_.isArray(where) || !where.every(_.isObject) || where.length === 0) throw new Error("invalid where clause condition provided"); // 用fs读取文件避免require缓存问题 const fileContent = fs.readFileSync(path.resolve(filePath), "utf-8"); const content = JSON.parse(fileContent); // 全树遍历执行操作 traverseAndOperate(content, where, data, act); // 写回原文件 fs.writeFileSync(path.resolve(filePath), JSON.stringify(content, null, 2)); console.log("操作完成,修改后的内容:\n", JSON.stringify(content, null, 2)); return content; } catch(err) { console.log("ERROR :: CONSUMER ::", err.message); throw err; } } // 调用示例:新增属性 const conditions = [ { name: "Essential Large" }, { selected: true } ]; const newdata = { description: "our best service" }; consumer("./sample.json", conditions, newdata, "add"); // 调用示例:删除匹配节点的description属性 // consumer("./sample.json", conditions, ["description"], "delete"); // 调用示例:删除所有匹配的数组元素 // consumer("./sample.json", conditions, null, "delete");
注意事项
- 代码默认对所有匹配节点批量操作,数千份小体积JSON文件运行无性能压力,若需处理超大文件可改为异步流式处理
- 删除操作区分两种场景:传入数组格式的data会删除匹配对象的对应键,传入null会删除整个匹配节点
- 若需避免修改原文件,可修改写回逻辑将结果输出到新的文件路径
内容的提问来源于stack exchange,提问作者Meet
相关产品推荐
相关产品推荐

