2017-01-31 11 views
0

Я хочу преобразовать некоторые сложные объекты JavaScript в JSON (например, перед сохранением данных в файл). Эти объекты могут содержать произвольно вложенные значения данных любого типа, включая карты и/или наборы ES6/ES2015. напримерМожно ли включать вложенные карты и наборы ES2015 в JSON?

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

Однако JSON.stringify вызывает отображение/набор данных, которые будут потеряны. Итак, есть ли способ сохранить данные на картах и ​​наборах при сохранении в виде JSON?

ответ

0

Вы можете использовать функцию replacer с JSON.stringify и соответствующей reviver функции с JSON.parse, который преобразует карты и/или наборы для стандартных массивов JavaScript и обратно. например

заменителями и Reviver функции:

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; 

Этот метод использует, например, в пределах a map-to-array conversion strategyJSON.stringify и одновременно «марки» новый массив как будто они были получены из карты, например, он преобразует 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.)