[This is first question on SO, so apologize me for any mistake]
I'm trying to save a Map, like the one below, in a cookie.
var myMap = new Map();
myMap.set("k1", {
a1: "...",
a2: "...",
a3: "..."
});
For this, I have to format as JSON. I tried many methods, like:
$.toJSON(myMap)
$.param(myMap)
JSON.stringify(myMap)
But none of them seems to work...
So, I did this:
var serial = [];
myMap.forEach(function(value){
serial.push(value);
});
var result = $.toJSON(serial)
(Having to reconstruct the key on decoding the JSON...)
There is a better way to serialize a Map object?
[This is first question on SO, so apologize me for any mistake]
I'm trying to save a Map, like the one below, in a cookie.
var myMap = new Map();
myMap.set("k1", {
a1: "...",
a2: "...",
a3: "..."
});
For this, I have to format as JSON. I tried many methods, like:
$.toJSON(myMap)
$.param(myMap)
JSON.stringify(myMap)
But none of them seems to work...
So, I did this:
var serial = [];
myMap.forEach(function(value){
serial.push(value);
});
var result = $.toJSON(serial)
(Having to reconstruct the key on decoding the JSON...)
There is a better way to serialize a Map object?
Share Improve this question edited Oct 15, 2017 at 4:47 Marcos Paulo asked Oct 14, 2017 at 5:22 Marcos PauloMarcos Paulo 3373 silver badges10 bronze badges 04 Answers
Reset to default 9Not exactly a typical "stringify", but you can use the spread operator bined with JSON.stringify()
, that will give you an array...
var myMap = new Map();
myMap.set("k1", { a1: "...", a2: "...", a3: "..." });
myMap.set("k2", { b1: "...", b2: "...", b3: "..." });
var myJSON = JSON.stringify([...myMap]);
alert(myJSON);
This will give you...
[["k1",{"a1":"...","a2":"...","a3":"..."}],["k2",{"b1":"...","b2":"...","b3":"..."}]]
And to convert it to Map again...
var recoveredMap = new Map(JSON.parse(myJSON));
While spread operator is good if you want to stringify immediate maps, you'll face problems if they are nested within any data structures.
Both JSON.stringify and JSON.parse support callback functions:
JSON.stringify(value[, replacer[, space]])
JSON.parse(text[, reviver])
So you can write functions such as:
function replacer (key, value){
if (value.__proto__ == Map.prototype) {
return {
_type: "map",
map: [...value],
}
} else return value;
}
function reviver (key, value){
if (value._type == "map") return new Map(value.map);
else return value;
}
Now you can easily stringify/parse maps no matter how deep they are nested:
let obj = {
map: new Map([
[1, new Map([
[1,2],
[3,4],
])],
[2,3],
]),
};
console.log(obj);
let str = JSON.stringify(obj, replacer);
console.log(str);
console.log(JSON.parse(str));
console.log(JSON.parse(str, reviver));
What about using Array.from to convert your Map
into an array
// initialize the map
var myMap = new Map();
myMap.set("k1", {
a1: "...",
a2: "...",
a3: "..."
});
myMap.set("k2", {
a1: "...",
a2: "...",
a3: "..."
});
// serialize the map by converting it to an array
var mapAsArray = Array.from(myMap);
console.log('Map as array ',mapAsArray);
var serializedMap = JSON.stringify(mapAsArray);
console.log(serializedMap)
// deserialize into a new map
var map = new Map(JSON.parse(serializedMap))
console.log(map.size)
There's a new JS feature - Object.fromEntries. It can parse a map into an object
const obj = {a: 1, b: 2}
const map = new Map(Object.entries(obj))
const objectCopy = Object.fromEntries(map)
Compatibility is ok (Chrome, FF, Safari) and a polyfill exists. We can also expect patibility to spread to all browsers since fromEntries is a "stage 4" proposal (approved).
See Compatibility here