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 添加到setmap 的提议被拒绝: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字符串化一个集合的主要内容,如果未能解决你的问题,请参考以下文章

解析字符串化 JSON 字符串时出错

在 AWS AppSync 中为 SQL 查询字符串化 JSON 对象

限制 JSON 字符串化深度

使用两组双引号取消嵌套字符串化 JSON

jQuery 1.4.1 中缺少 JSON 字符串化?

java 怎么把对象集合转换成json