网站搜索

typescript - 使用递归更改 json 中的值


我正在尝试使用 TypeScript 通过递归函数更改 JSON 的值。我知道如何显示所有键或值,但我不确切知道如何更改值。

我有这个 JSON 和这段代码:

var json = {
    "a" : "hello",
    "b" : "bye",
    "c" : {
        "d" : "test1",
        "e" : "test2"
    },
    "f" : {
        "g" : {
             "h" : "test3",
             "i" : "test4"
         }
    }
};

changeInJson(id: string, value: string, level: number, json: object): void {
    level = level || 0;
    for (var property in json) {
        if (typeof json[property] === 'object') {
            this.changeInJson(id, value, ++level, json[property]);
        } else {
            console.log(property);
            if(property === id) {
                //change value in json
                console.log("Yes");
            }
        }
    }
};

changeInJson("i", "changed", 0, json);
console.log(json);

在这个例子中,我知道 JSON 键,但实际上我需要以某种方式保存到达键“i”的所有路径,而这正是我不知道如何做的。

谢谢

答案#1

对于这个特定的递归任务,没有必要跟踪递归的深度(或级别),因为当所考虑的对象没有子对象时,自然会达到递归终止情况。需要注意的是,包含循环引用的对象会导致递归爆炸,除非你采取特殊措施来跟踪已经访问过的对象。

一种通用的方法来更改任何名为 id 的属性/嵌套属性可能类似于:

const changeInJson = (id: string, value: string, obj: object): void => {
  for (const [k, v] of Object.entries(obj)) {
    if (k === id) {
      obj[k] = value;
    } else if (typeof v === "object") {
      changeInJson(id, value, v);
    }
  }
};

如果我没记错,你至少需要在你的 tsconfig.json 文件中使用 es2017 库来使用 Object.entries

我将把数组处理的添加留给读者自己练习 :)

答案#2

@spender 的解决方案几乎很好,只是它在处理空值时会出错...

这是修复方法:

const changeInJson = (id: string, value: string, obj: object): void => {
  for (const [k, v] of Object.entries(obj)) {
    if (k === id) {
      obj[k] = value;
    } else if (v && typeof v === "object") {
      changeInJson(id, value, v);
    }
  }
};