如何在JSON.parse的reviver函数中展开对象值并移除原键
问题描述
我希望能够在JSON.parse的reviver函数中展开指定条目的值,同时删除对应的原始键,但直接返回展开后的值无法实现该效果。
示例代码
JavaScript逻辑代码:
const json = {a: 'foo', b: {c: 1, d: '2'}} const stringify = JSON.stringify(json) const parsed = JSON.parse(stringify, function(k, v) { if(k === 'b') { return {...v} } else { return v } }) document.getElementById("app").innerHTML = `<pre>${JSON.stringify(parsed, null, 2)}</pre>`;
配套页面HTML代码:
<div id="app"></div>
期望输出
{ "a": "foo", "c": 1, "d": "2" }
原因说明
JSON.parse的reviver函数本身不支持将返回值展开合并到父级对象,reviver的返回值只会直接替换当前遍历到的键对应的值,不会自动做属性合并。原写法中返回{...v}本质和直接返回v没有区别,最终b键依然会挂载在父对象上,无法达到删除原键、展开属性的效果。
实现方法
利用reviver深度优先遍历的特性,在遍历到父级普通对象时,检测是否存在需要展开的子键,手动完成属性合并后删除原始键即可:
const parsed = JSON.parse(stringify, function(k, v) { // 仅处理普通对象类型的值,跳过数组、null等特殊情况 if (typeof v === 'object' && v !== null && !Array.isArray(v)) { // 检测到存在需要展开的键b if (Object.prototype.hasOwnProperty.call(v, 'b')) { // 将b下的所有属性合并到当前对象 Object.assign(v, v.b); // 删除原始的b键 delete v.b; } } return v })
运行上述代码得到的结果和期望输出完全一致。如果有多个需要展开的键,只需要在判断逻辑中追加对应的处理分支即可,深度优先的遍历顺序会保证内层待展开的键先完成处理,不会出现属性丢失问题。
内容的提问来源于stack exchange,提问作者baba-dev
相关产品推荐
相关产品推荐

