React中如何通过键名动态获取多层级JSON对象中的数据
如何通过点分隔的键名获取多层级JSON/对象的值?
我有如下多层级数据:
const data = { level11: "l11", level12: { level21: "l21", level22: { level31: "l31", level32: "l32" } }, level13: [{ level131: "a" }, { level132: "b" }] };
直接用data.level11这类方式能轻松拿到对应值,但现在我手里的键名是"level11"或者"level12.level22.level31"这种点分隔的格式。单层的键名可以用data["level11"]访问,但多层级的情况就搞不定了,而且数组类型的节点也处理不了。
我试过下面这个递归方法,但它没法处理数组或对象类型的返回值:
generateData = (data, key) => { if (!key.includes(".")) return data[key]; var p = key.split(".")[0]; var ndata = data[p]; if(!ndata) return; var newkey = key .split(".") .filter((o, i) => i !== 0) .join("."); return this.generateData(ndata, newkey); };
完整的React组件代码如下:
export default function App() { const data = { level11: "l11", level12: { level21: "l21", level22: { level31: "l31", level32: "l32" } }, level13: [{ level131: "a" }, { level132: "b" }] }; generateData = (data, key) => { if (!key.includes(".")) return data[key]; var p = key.split(".")[0]; var ndata = data[p]; var newkey = key .split(".") .filter((o, i) => i !== 0) .join("."); return this.generateData(ndata, newkey); }; return ( <div className="App"> <h1>Hello CodeSandbox</h1> <span>{this.generateData(data, "level12.level22.level31")}</span> </div> ); }
解决方案
方法1:优化递归逻辑,兼容数组和对象
修改函数逻辑,确保每一步都能正确处理对象和数组类型的节点,同时支持数组索引格式的键名(比如level13.0):
const generateData = (data, key) => { // 空数据或空键直接返回 if (!data || !key) return undefined; const keys = key.split("."); let current = data; for (const k of keys) { // 尝试将键转为数组索引 const index = parseInt(k, 10); // 数组类型且索引有效时用索引访问,否则用键名访问 current = Array.isArray(current) && !isNaN(index) ? current[index] : current[k]; // 中途找不到对应值直接返回 if (current === undefined) return undefined; } return current; };
方法2:使用reduce简化实现
用数组reduce方法可以更简洁地实现相同逻辑,同样兼容对象和数组:
const generateData = (data, key) => { return key.split(".").reduce((current, k) => { if (!current) return undefined; const index = parseInt(k, 10); return Array.isArray(current) && !isNaN(index) ? current[index] : current[k]; }, data); };
修改后的完整组件代码
export default function App() { const data = { level11: "l11", level12: { level21: "l21", level22: { level31: "l31", level32: "l32" } }, level13: [{ level131: "a" }, { level132: "b" }] }; const generateData = (data, key) => { return key.split(".").reduce((current, k) => { if (!current) return undefined; const index = parseInt(k, 10); return Array.isArray(current) && !isNaN(index) ? current[index] : current[k]; }, data); }; return ( <div className="App"> <h1>Hello CodeSandbox</h1> <div>level11: {generateData(data, "level11")}</div> <div>level12.level22.level31: {generateData(data, "level12.level22.level31")}</div> <div>level13.0.level131: {generateData(data, "level13.0.level131")}</div> <div>level13.1: {JSON.stringify(generateData(data, "level13.1"))}</div> </div> ); }
这个修改后的函数可以处理:
- 普通对象的多层级键名(如
level12.level22.level31) - 数组索引(如
level13.0) - 返回对象/数组类型的值(比如
level13.1会返回{ level132: "b" })
内容的提问来源于stack exchange,提问作者vicky
相关产品推荐
相关产品推荐

