使用 JSON.parse reviver 强制结果对象中的值未定义,而不是导致属性被省略

Ste*_*n G 5 javascript json deserialization json-deserialization

JSON.parse将序列化的 JSON 作为参数并将其反序列化。第二个(可选)参数是一个 reviver 函数,它采用键和值并返回反序列化对象中的替换值。据记录,恢复程序如果返回未定义或什么也不返回,则所讨论的属性将从结果反序列化对象中省略。

我遇到一种情况,我希望将有问题的属性包含在结果反序列化对象中,其值为未定义。

因此,例如,以下内容目前是正确的:

JSON.parse(JSON.stringify({a: 1, b:2}), (k, v) => v===2 ? undefined : v);
// result of this is {a:1}, as is documented/expected.
Run Code Online (Sandbox Code Playgroud)

但如果我真的想要结果怎么办

{a:1, b:undefined}
Run Code Online (Sandbox Code Playgroud)

有没有办法编写reviver来做到这一点?

我特别不想在反序列化后再次迭代该对象,所以请不要建议将其作为解决方案。另外,我特别不希望将 b 设置为空。我真的希望它作为一个属性存在,其值未定义。

这可能根本不可能,但我希望有人有一个好主意!

第一次编辑:

第一个建议是很好的尝试,但我也需要它在深层结构中工作,所以如下:

JSON.parse(JSON.stringify({
    a: 1,
    b:{
        c: 1,
        d: 2,
        e: [
            1, 
            2,
            {
                f: 1,
                g: 2
            },
            4
        ]
    }
}), (k, v) => v===2 ? undefined : v);
Run Code Online (Sandbox Code Playgroud)

在我的理想世界中应该产生:

{
    a: 1,
    b:{
        c: 1,
        d: undefined,
        e: [
            1, 
            undefined,
            {
                f: 1,
                g: undefined
            },
            4
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*yet 1

我怀疑这可以通过简单的恢复器和 来完成JSON.parse

我不知道这是否会满足您的限制,而且它很难看,但这里有一个方法:包装JSON.parse一些存储来自恢复器的密钥的东西undefined,并将它们添加回最后。这并不需要再次迭代您的对象(您明确拒绝了该对象),但它确实迭代了undefined键列表:

const myParse = (obj, reviver) => {
  if (typeof reviver !== 'function') {
    return JSON.parse(obj)
  }
  const undefs = []
  const rev = (k, v) => {
    const val = reviver(k, v)
    if (typeof val === 'undefined') {
      undefs.push(k)
    }
    return val;
  }
  const ret = JSON.parse(obj, rev)
  undefs.forEach(k => ret[k] = undefined)
  return ret
}

const result = myParse(
  JSON.stringify({a: 1, b:2}), 
  (k, v) => v===2 ? undefined : v
)

console.log(result)
Run Code Online (Sandbox Code Playgroud)