
本文介绍一种通用、可扩展的方法,将形如 `"a.b.c"` 的键名自动解析为多层嵌套对象结构,并将对应值精准插入最深层,彻底避免硬编码层级判断。
在处理配置化数据(如 IoT 设备标签、JSON Schema 路径映射或动态表单字段)时,常需将扁平化的点号分隔键(如 "0_tags.0.Various.Test-String")还原为树状嵌套对象。原始代码仅支持固定两层(item[0] 和 item[1]),无法应对任意深度的路径,导致可维护性差且易出错。
解决的核心思路是:将路径字符串拆分为键数组,再通过递归或迭代方式逐层“钻取”并创建缺失节点,最终在叶子位置赋值。以下提供两种生产就绪的实现方案:
✅ 方案一:递归实现(清晰易懂)
function createNestedObject(obj, keys, value) {
const [head, ...tail] = keys; // ES6 解构,兼容现代环境
if (tail.length === 0) {
obj[head] = value;
} else {
obj[head] = obj[head] || {};
createNestedObject(obj[head], tail, value);
}
}
// 使用示例
const tagObject = {
"0_tags.0": { common: {}, native: { topic: "Stromerfassung_251/Zähler0-Leistung" } },
"0_tags.0.Various": { common: {}, native: { topic: "Stromerfassung_251/Zähler0-Leistung" } },
"0_tags.0.Various.Stromerfassung_251/Zähler0-Leistung": { common: {}, native: { topic: "Stromerfassung_251/Zähler0-Leistung" } },
"0_tags.0.Various.Test-String": { common: {}, native: { topic: "Stromerfassung_251/Zähler0-Leistung" } },
"0_tags.0.Various.battery_charge": { common: {}, native: { topic: "Stromerfassung_251/Zähler0-Leistung" } }
};
const result = {};
for (const key in tagObject) {
createNestedObject(result, key.split('.'), tagObject[key]);
}
console.log(JSON.stringify(result, null, 2));✅ 方案二:迭代实现(无栈溢出风险,推荐用于超深路径)
function setNestedProperty(obj, path, value) {
const keys = path.split('.');
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (current[key] === undefined || typeof current[key] !== 'object') {
current[key] = {};
}
current = current[key];
}
current[keys[keys.length - 1]] = value;
}
// 批量应用
const result2 = {};
Object.entries(tagObject).forEach(([key, value]) => {
setNestedProperty(result2, key, value);
});⚠️ 注意事项与最佳实践
- 键名合法性:若路径含特殊字符(如 . / [),需提前转义或使用 JSONPath 等专用库;
- 性能考量:对海量键(>10k),迭代版比递归版更稳定(避免 V8 栈限制);
- 空值防御:示例中使用 obj[head] = obj[head] || {} 替代 undefined 判断,更简洁鲁棒;
- 不可变更新:如需函数式编程风格,可封装为返回新对象的纯函数(配合 structuredClone 或 Lodash set);
- 类型安全:TypeScript 用户可定义泛型约束,确保 keys 为 string[],value 类型与目标结构一致。
该方法已广泛应用于 Node.js 配置加载器、前端状态归一化(如 Redux Toolkit 的 createEntityAdapter 路径映射)及低代码平台元数据解析场景——一次编写,永久适配任意嵌套深度。










