我可以在JSON中包含嵌套的ES2015地图和集合吗?

时间:2017-01-31 21:17:08

标签: javascript json dictionary ecmascript-6 set

我想将一些复杂的JavaScript对象转换为JSON(例如,在将数据保存到文件之前)。这些对象可以包含任意类型的任意嵌套数据值,包括ES6 / ES2015映射和/或集合。 e.g。

const myOriginalObject = {
    a: [1, new Set([2, new Map()]), 3],
    c: {d: new Map([['e', 4], ['f', new Set()]])}
};

但是,JSON.stringify会导致地图/集数据丢失。那么,有没有一种方法可以在存储为JSON时在地图和集合中维护数据?

1 个答案:

答案 0 :(得分:0)

您可以将replacer函数与JSON.stringifyreviver函数一起使用JSON.parse,将地图和/或集合转换为标准JavaScript数组,然后再将其转换回来。 e.g。

替换和启动功能:

const replacer = (k, v) =>
    v instanceof Map ? ({_WAS_MAP: [...v]}) :
    v instanceof Set ? ({_WAS_SET: [...v]}) : v;

const reviver = (k, v) =>
    v && v._WAS_MAP ? new Map(v._WAS_MAP) :
    v && v._WAS_SET ? new Set(v._WAS_SET) : v;

此技术使用例如JSON.stringify内的a map-to-array conversion strategy,同时将新数组“标记”为已从地图中导出,例如它会将Map { 'a' => 1 }转换为{"_WAS_MAP":[["a",1]]}。然后,稍后,JSON.parse可以查找标记为_WAS_MAP的属性,并知道将这些属性转换回地图。类似的策略可以用于集合。

示例代码:

const myOriginalObject = {
    a: [1, new Set([2, new Map()]), 3],
    c: {d: new Map([['e', 4], ['f', new Set()]])}
};

console.log('original:', myOriginalObject);
const mySavedJson = JSON.stringify(myOriginalObject, replacer);
console.log('JSON:', mySavedJson);
const myRetrievedObject = JSON.parse(mySavedJson, reviver);
console.log('retrieved:', myRetrievedObject); // all data is recovered

输出(为清晰起见编辑了空格):

original:  { a :[1,       Set  {2,       Map  {}  },3], c :{ d:        Map  { 'e' => 4,  'f' =>     Set  {}   }}}
JSON:      {"a":[1,{"_WAS_SET":[2,{"_WAS_MAP":[]}]},3],"c":{"d":{"_WAS_MAP":[["e",   4],["f",{"_WAS_SET":[]}]]}}}
retrieved: { a :[1,       Set  {2,       Map  {}  },3], c :{ d:        Map  { 'e' => 4,  'f' =>     Set  {}   }}}

(我没有将上述代码包含在正常工作的代码段中,因为console.log显示地图并在运行时如上所述设置数据,例如,节点,它在运行时不会显示StackOverflow上的代码片段。)