【问题标题】:Detecting parent object when calling JSON.stringify调用 JSON.stringify 时检测父对象
【发布时间】:2020-09-10 04:17:29
【问题描述】:

我有一个对象,即:

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

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

类似于以下伪代码:

     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 在运行时的标题

【问题讨论】:

  • 想要的输出是什么?
  • 所需的输出是 json。即:{ "item1" : "value1", "item2" : "value2", "item3" : { "item4" : "theSomeOtherValue", "item5" : "theSomeOtherValue" }

标签: javascript json stringify


【解决方案1】:

您至少可以在这里采取两种方法。

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

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

【讨论】:

    【解决方案2】:

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

    这种方法没有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);

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 这个答案已经在几分钟前发布了。请在回答之前检查以前的答案,这样您就不会只是重新发布已经给出的答案。
      猜你喜欢
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 2012-12-01
      • 2011-08-26
      • 2013-11-07
      • 2021-10-21
      • 2021-07-20
      • 2014-09-05
      相关资源
      最近更新 更多