When you have key-value data whose keys you don’t know in advance, it’s generally better to store it in an ES6 Map than in an object. But how do you convert Maps to and from JSON? This blog post tells you.
Background knowledge:
If a Map contains arbitrary (JSON-compatible) data, we can convert it to JSON by encoding it as an Array of key-value pairs (2-element Arrays).
The spread operator lets you convert a Map to an Array of pairs:
> let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
> [...myMap]
[ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
The Map
constructor lets you convert an Array of pairs to a Map:
> new Map([[true, 7], [{foo: 3}, ['abc']]])
Map {true => 7, Object {foo: 3} => ['abc']}
Let’s use this knowledge to convert any Map with JSON-compatible data to JSON and back:
function mapToJson(map) {
return JSON.stringify([...map]);
}
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
The following interaction demonstrates how these functions are used:
> let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
> mapToJson(myMap)
'[[true,7],[{"foo":3},["abc"]]]'
> jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
Map {true => 7, Object {foo: 3} => ['abc']}
Whenever a Map only has strings as keys, you can convert it to JSON by encoding it as an object.
The following two function convert string Maps to and from objects:
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
// We don’t escape the key '__proto__'
// which can cause problems on older engines
obj[k] = v;
}
return obj;
}
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
Let’s use these two functions:
> let myMap = new Map().set('yes', true).set('no', false);
> strMapToObj(myMap)
{ yes: true, no: false }
> objToStrMap({yes: true, no: false})
[ [ 'yes', true ], [ 'no', false ] ]
With these helper functions, the conversion to JSON works as follows:
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
This is an example of using these functions:
> let myMap = new Map().set('yes', true).set('no', false);
> strMapToJson(myMap)
'{"yes":true,"no":false}'
> jsonToStrMap('{"yes":true,"no":false}');
Map {'yes' => true, 'no' => false}