调用 JSON.stringify 时检测父对象

cod*_*ght 3 javascript json stringify

我有一个对象,即:

{
  item1: "value1",
  item2: "value2",
  item3: { 
      item4: "value4",
      item5: "value5" 
  }
}
Run Code Online (Sandbox Code Playgroud)

我想JSON.stringify与一个replacer函数一起使用,该函数对 item3 的内部属性4 和 5 有不同的作用。
那怎么办?

类似于以下伪代码:

     return JSON.stringify(obj, (key, val) => {
         if (key is child of Item3) {
             return someOtherValue;
         } else {
             return val; 
         } 
}
Run Code Online (Sandbox Code Playgroud)

所需的输出是 json。IE:

{ 
  "item1" : "value1", 
  "item2" : "value2", 
  "item3" : { 
      "item4" : "theSomeOtherValue", 
      "item5" : "theSomeOtherValue"
}
Run Code Online (Sandbox Code Playgroud)

编辑
项目 4 和 5 事先未知,它们是动态生成的。
我只知道item3运行时的标题

T.J*_*der 8

您至少可以采用两种方法。

  1. 在replacer函数中,this是被处理的对象,所以当item4item5被处理的时候,this指的是item3对象。因此,如果该对象有任何内容可以让您识别它,您可以通过查看this. (一定要使用传统函数,而不是箭头函数,以便JSON.stringify可以this在替换器调用期间设置什么。)

  2. replacer 函数是用正在处理的键和值来调用的,所以如果对象("item3")的键是唯一的,你可以在看到它时做特殊处理。

以下是 #1 的几个示例:

举例来说,如果你要的对象的引用,你可以比较thisobj.item3

const obj = {
    item1: "value1",
    item2: "value2",
    item3: { 
        item4: "value4",
        item5: "value5" 
    }
};
console.log(JSON.stringify(obj, function(key, value) {
//                              ^^^^^^^^^????? Traditional function, not arrow function
    if (this === obj.item3) {
        console.log("do something different, it's " + key);
        return "theSomeOtherValue";
    }
    return value;
}));
Run Code Online (Sandbox Code Playgroud)

如果您没有对它的引用,您可以使用您拥有的任何其他识别信息。例如,使用示例数据,您可以看到它具有item4item5属性:

console.log(JSON.stringify({
    item1: "value1",
    item2: "value2",
    item3: { 
        item4: "value4",
        item5: "value5" 
    }
}, function(key, value) {
// ^^^^^^^^^????? Traditional function, not arrow function
    if (this.hasOwnProperty("item4") && this.hasOwnProperty("item5")) {
        console.log("do something different, it's " + key);
        return "theSomeOtherValue";
    }
    return value;
}));
Run Code Online (Sandbox Code Playgroud)

不过,这只是两个例子;关键是this对象被字符串化。

这是#2的示例:

console.log(JSON.stringify({
    item1: "value1",
    item2: "value2",
    item3: { 
        item4: "value4",
        item5: "value5" 
    }
}, (key, value) => { // It's okay if this one is an arrow function, we're not relying on
                     // `JSON.stringify` setting `this` for us
    if (key === "item3") {
        return {
            item4: "theSomeOtherValue",
            item5: "theSomeOtherValue"
        };
    }
    return value;
}));
Run Code Online (Sandbox Code Playgroud)

如果您需要正在处理的对象的完整路径,那就有点麻烦了,但是您可以得到它:

let paths = new Map();
console.log(JSON.stringify({
    item1: "value1",
    item2: "value2",
    item3: { 
        item4: "value4",
        item5: "value5" 
    },
    item6: {
        item3: {
            item4: "non-special item4",
            item5: "non-special item5"
        }
    }
}, function(key, value) {
// ^^^^^^^^^????? Traditional function, not arrow function
    const path = paths.get(this);
    // Special processing for the properties of root.item3
    if (path === "root.item3") {
        return key === "item4" || key === "item5"
            ? "theSomeOtherValue"
            : value;
    }

    // Keep track of the path of the object
    for (const [k, v] of Object.entries(this)) {
        if (typeof v === "object") {
            if (path) {
                // The regex checks for property names that aren't valid(ish)
                // property names so we can use brackets notation
                paths.set(v, path + (/^\w+$/.test(k) ? "." + k : `[${JSON.stringify(k)}]`));
            } else {
                paths.set(v, "root");
            }
        }
    }
    return value;
}));
Run Code Online (Sandbox Code Playgroud)