JSON 字符串化一个集合

IT技术 javascript json ecmascript-6
2021-01-14 18:30:51

一个JSON.stringify()怎么会是一个Set

在 Chromium 43 中不起作用的事情:

var s = new Set(['foo', 'bar']);

JSON.stringify(s); // -> "{}"
JSON.stringify(s.values()); // -> "{}"
JSON.stringify(s.keys()); // -> "{}"

我希望得到类似于序列化数组的东西。

JSON.stringify(["foo", "bar"]); // -> "["foo","bar"]"
3个回答

JSON.stringify 不直接使用集合,因为存储在集合中的数据不存储为属性。

但是您可以将集合转换为数组。然后,您将能够正确地对其进行字符串化。

以下任何一项都可以解决问题:

JSON.stringify([...s]);
JSON.stringify([...s.keys()]);
JSON.stringify([...s.values()]);
JSON.stringify(Array.from(s));
JSON.stringify(Array.from(s.keys()));
JSON.stringify(Array.from(s.values()));
只是添加一些参考MDN有一些这个和其他相关技术的例子
2021-03-24 18:30:51
当前改进默认值的提议Set.prototype.toJSONgithub.com/DavidBruant/Map-Set.prototype.toJSON
2021-03-24 18:30:51
列表理解也可以工作: JSON.stringify([_ for (_ of s)])
2021-04-01 18:30:51
所有这样做的好方法,遗憾的是它们不能在 Chromium 43 中开箱即用,因为 spread 和 Array.from 尚未实现。看起来像 Babel 来救援。
2021-04-01 18:30:51
我正要求婚Array.from()但这在惯用语上看起来更好。
2021-04-05 18:30:51

使用这个JSON.stringify替代品:

(因为toJSON是遗留工件,更好的方法是使用自定义replacer,请参阅https://github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16

function Set_toJSON(key, value) {
  if (typeof value === 'object' && value instanceof Set) {
    return [...value];
  }
  return value;
}

然后:

const fooBar = { foo: new Set([1, 2, 3]), bar: new Set([4, 5, 6]) };
JSON.stringify(fooBar, Set_toJSON)

结果:

"{"foo":[1,2,3],"bar":[4,5,6]}"
相应的复活者留给读者作为练习?;-)
2021-03-30 18:30:51
ES6 有缩短版本 JSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
2021-04-04 18:30:51

尽管上述所有工作,我建议您将 set 子类化并添加一个toJSON方法以确保它正确地字符串化。特别是如果您要经常进行字符串化。我在我的 Redux 商店中使用了集合,需要确保这从来都不是问题。

这是一个基本的实现。命名只是为了说明选择你自己的风格。

class JSONSet extends Set {
    toJSON () {
        return [...this]
    }
}

const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))
constructor不需要覆盖
2021-03-17 18:30:51
我不会推荐这种方法,因为它toJSON被认为是遗留功能。提议增加toJSONsetmap被拒绝:github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
2021-04-04 18:30:51