Problem:
I have a Map instance in which it's keys have Map instance and values too, imagine a nested Map situation. I call this Nested Map. See below:
const m = new Map([["a", "aa"], ["m", new Map([["b", "bb"], ["mm", new Map()]])]]);
I wanted to serialize this whole thing, and store in local storage, of course I have to spread it into an array mapping first as we know it won't work as expected for Maps.
Applying spread operator or calling the entries method on a Map that doesn't have another Map instance as its key value will work as expected. But having a nested situation like that, only works for the outer Map instance. Even the entries method will create iterator just for the main instance you're calling it on, not for the inner ones.
My way around this is, using a replacer function that spreads values which are map instances into an array (See below), before storing in local storage.
JSON.stringify(obj, (key, value) => {
if (({}).toString.call(value) === '[Object Map]') return [...value];
return value;
});
Proposal:
Let's have a way in which Map instances... maybe have a method that create iterators not just parsing main Map instance it is being called on, but also the key values which are Map instances also.
Also applying spread operator on it will spread from the main Map instance to the deepest key value Map instance, the inner key value Map instances will spread in an array too, so that, at the end we have an Array mapping in which the values for keys which previously have Map instances as values are now array mappings too, to the same level of initially nested Map instances. Imagine a deep flat situation, but not the array kind.
More interesting: A way to reverse the situation, so that we are back to our formal nested Map instances.
My way around is: getting my nested array from the local storage, for...of looping through the whole nested array, setting keys and values all over again in the map, and if the value part of the destructure is an array, I set a Map instance as value for the current key, and setting the keys and values for that nested one too, in a nested for...of loop.
That's tedious for anyone, even the V8 engine.
Here:
for(const [key, value] of nestedArray) {
if (Array.isArray(value)) {
m.set(key, new Map());
for (const [key2, value2] of value) {
m.get(key).set(key2, value2);
}
} else {
m.set(key, value);
}
}
/*If **value2** is an array, this keeps growing...
There might be way to refactor this, maybe
with the **reduce method**, but it's still an hack
that might cause issues if you don't know what
you're doing.*/
This is what I do whenever I want a solution to problems like this.
It'd save precious time, if I can just make my nested Map, into array mappings, serialize it, store locally, parse it, and convert back to nested Map.
An idea while typing:
This can also allow, having an Array Mapping in which the value part (not all, of course) are array mappings too(instead of any other value or a map instance), go in the Map constructor, and having a dynamically created Map instance for each Array mapping at the value part in the Array Mapping passed to the Map constructor. See below:
const m = new Map([["a", "aa"], ["m", [["b", "bb"]]]]);
Pls if you don't understand this, please go through again, and if you know you understand and there's a way you can put it in a more understandable way, Pls let's know.
In a nutshell:
// From
const m = new Map([["a", "aa"], ["m", new Map([["b", "bb"], ["mm", new Map()]])]]);
// through
[...m]
// to
[
["a", "aa"],
["m", [["b", "bb"], ["mm", []]]],
]
I've not gone deep into using symbols in metaprogramming, if this'll be possible by metaprogramming my way through, let me know.
Thanks for reading through.