JSON字符串化一个集合
Posted
技术标签:
【中文标题】JSON字符串化一个集合【英文标题】:JSON stringify a Set 【发布时间】:2015-09-20 08:32:01 【问题描述】: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"]"
【问题讨论】:
密切相关:How do I persist a ES6 Map in localstorage (or elsewhere)? 【参考方案1】:之前所有方法的问题在于,它们都将集合转换为数组,从而丢失了集合和索引的全部要点。
你应该做的是使用一个对象来代替。 使用以下函数对其进行转换,或者将其创建为 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')
。
然后将其字符串化为一个没有问题的对象。
注意: 以下方法使用更多内存,因为它需要存储值和键。 但性能方面,与 Array.includes() 相比,它仍然是 O(1),后者是 O(n),甚至错过了使用 Set 的意义。
【讨论】:
【参考方案2】:虽然上述所有工作都有效,但我建议您将 set 子类化并添加一个 toJSON
方法以确保它正确地进行字符串化。特别是如果您要经常进行字符串化。我在我的 Redux 商店中使用集合,需要确保这绝不是问题。
这是一个基本的实现。命名只是为了说明点选自己的风格。
class JSONSet extends Set
toJSON ()
return [...this]
const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))
【讨论】:
我不推荐这种方法,因为toJSON
被认为是一个遗留功能。将toJSON
添加到set
和map
的提议被拒绝:github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
不需要覆盖constructor
。【参考方案3】:
使用这个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]"
【讨论】:
ES6 中有缩短版本JSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
对应的reviver留给读者练习吧? ;-)【参考方案4】:
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()));
【讨论】:
我要提议Array.from()
。但这看起来习惯上更好。
只是添加一些参考 MDN 有一些例子和其他相关技术
列表理解也可以工作:JSON.stringify([_ for (_ of s)])
所有很好的方法,遗憾的是它们不能在 Chromium 43 中开箱即用,因为 spread 和 Array.from 尚未实现。看起来像巴别塔救援。
当前改进Set.prototype.toJSON
默认值的提议:github.com/DavidBruant/Map-Set.prototype.toJSON以上是关于JSON字符串化一个集合的主要内容,如果未能解决你的问题,请参考以下文章