调用 JSON.stringify 时检测 parent object

Detecting parent object when calling JSON.stringify

我有一个 object,即:

{
  item1: "value1",
  item2: "value2",
  item3: { 
      item4: "value4",
      item5: "value5" 
  }
}

我想将 JSON.stringifyreplacer 函数一起使用,该函数 对项目 4 和 5 的作用不同 ,这是项目 3 的内部属性。
如何做到这一点?

类似于以下内容 pseudo-code:

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

所需的输出是 json。即:

{ 
  "item1" : "value1", 
  "item2" : "value2", 
  "item3" : { 
      "item4" : "theSomeOtherValue", 
      "item5" : "theSomeOtherValue"
}

编辑:
第 4 项和第 5 项是事先不知道的,它们是动态生成的。
我只在 运行 时间

知道 item3 的标题

这里至少有两种方法可以采用。

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

  2. replacer函数是通过处理的key和value调用的,所以如果对象的key("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;
}));

如果您没有它的参考资料,您可以使用您拥有的关于它的任何其他识别信息。例如,对于示例数据,您可以看到它具有 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;
}));

不过,这只是两个例子;关键是 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;
}));

如果你需要被处理对象的完整路径,那就比较麻烦了,不过你可以得到:

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;
}));

JSON.stringify 接受替换函数作为第二个参数(并提供当前对象被迭代为 this)所以你可以这样做:

return JSON.stringify(obj, function(key, val) {
    if (this === obj.item3) {
        return "theSomeOtherValue";
    }
    return val;
});

实现相同目的的另一种方法(使用当前 key 而不是 this 对象引用):

return JSON.stringify(obj, function(key, val) {
    if (key === "item4" || key === "item5") {
        return "theSomeOtherValue";
    }
    return val;
});

您可以将找到的所需对象存储在闭包中,并根据对象更改 return 值。

这种方法有效没有this

function replacer(parent) {
    let reference = {};
    return function (key, val) {
        if (key === parent) reference = val;
        return key in reference
            ? '#' + val
            : val; 
    };
}

var obj = { item1: "value1", item2: "value2", item3: { item4: "value4", item5: "value5" } },
    json = JSON.stringify(obj, replacer('item3'));

console.log(json);