JSON 字符串化一个集合

一个 Stringify ()一个 预备怎么样?

在 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"]"
54408 次浏览

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

虽然上面的所有工作,我建议您子类设置并添加一个 toJSON方法,以确保它的正确字符串。特别是如果你要经常把它们串起来的话。我在我的 Redux 商店中使用集合,并且需要确保这永远不会成为一个问题。

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

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


const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))

你可以给 JSON.stringify传递一个“替换器”函数:

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


JSON.stringify(
fooBar,
(_key, value) => (value instanceof Set ? [...value] : value)
);

结果:

"{"foo":[1,2,3],"bar":[4,5,6]}"

toJSON是一个遗留的工件,更好的方法是使用定制的 replacer ,参见 < a href = “ https://github.com/DavidBruant/Map-Set.Prototype.toJSON/issues/16”rel = “ norefrer”> https://github.com/davidbruant/map-set.prototype.tojson/issues/16

前面所有方法的问题在于,它们都将集合转换为 Array,而 Array 缺少 Set 和 index 的整个点。

你应该做的是使用一个对象来代替。 要么用下面的函数转换它,要么简单地将它创建为 Object 而不是 Set。

const mySet = new Set(['hello', 'world']);
const myObj = {};
for (let value of mySet.values()) {
myObj[value] = true;
}

然后代替使用 mySet.has('hello')myObj.hasOwnProperty('hello')

然后把它作为一个没有问题的对象串起来。

注意 : 下面的方法使用更多的内存,因为它需要存储值和键。 但是在性能方面,它仍然是 O (1) ,而 Array.include ()是 O (n) ,甚至错过了使用 Set 的要点。