Je voudrais commencer à utiliser ES6 Map à la place des objets JS, mais je suis retenu car je ne sais pas comment JSON.stringify () une Map. Mes clés sont garanties être des chaînes et mes valeurs seront toujours des listes. Dois-je vraiment écrire une méthode de wrapper pour sérialiser?
Tu ne peux pas.
Les clés d'une carte peuvent être n'importe quoi, y compris des objets. Mais la syntaxe JSON autorise uniquement les chaînes en tant que clés. Donc, c'est impossible dans un cas général.
Mes clés sont garanties être des chaînes et mes valeurs seront toujours des listes
Dans ce cas, vous pouvez utiliser un objet simple. Il aura ces avantages:
Vous ne pouvez pas directement hiérarchiser l'instance Map
car elle n'a aucune propriété, mais vous pouvez la convertir en un tableau de n-uplets:
jsonText = JSON.stringify(Array.from(map.entries()));
Pour l'inverse, utilisez
map = new Map(JSON.parse(jsonText));
Tous les deux JSON.stringify
et JSON.parse
supporte un deuxième argument. replacer
et reviver
respectivement. Avec replacer et reviver ci-dessous, il est possible d'ajouter le support pour les objets Map natifs, y compris les valeurs profondément imbriquées.
function replacer(key, value) {
const originalObject = this[key];
if(originalObject instanceof Map) {
return {
dataType: 'Map',
value: Array.from(originalObject.entries()), // or with spread: value: [...originalObject]
};
} else {
return value;
}
}
function reviver(key, value) {
if(typeof value === 'object' && value !== null) {
if (value.dataType === 'Map') {
return new Map(value.value);
}
}
return value;
}
sage:
const originalValue = new Map([['a', 1]]);
const str = JSON.stringify(originalValue, replacer);
const newValue = JSON.parse(str, reviver);
console.log(originalValue, newValue);
Nidification en profondeur avec combinaison de tableaux, d'objets et de cartes
const originalValue = [
new Map([['a', {
b: {
c: new Map([['d', 'text']])
}
}]])
];
const str = JSON.stringify(originalValue, replacer);
const newValue = JSON.parse(str, reviver);
console.log(originalValue, newValue);
Bien que ecmascript n’ait pas encore fourni de méthode, ceci peut toujours être fait en utilisant JSON.stingify
si vous mappez le Map
à une primitive JavaScript. Voici l'exemple Map
que nous allons utiliser.
const map = new Map();
map.set('foo', 'bar');
map.set('baz', 'quz');
Vous pouvez convertir en littéral objet JavaScript avec la fonction d'assistance suivante.
const mapToObj = m => {
return Array.from(m).reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
};
JSON.stringify(mapToObj(map)); // '{"foo":"bar","baz":"quz"}'
La fonction d'assistance pour celui-ci serait encore plus compacte
const mapToAoO = m => {
return Array.from(m).map( ([k,v]) => {return {[k]:v}} );
};
JSON.stringify(mapToAoO(map)); // '[{"foo":"bar"},{"baz":"quz"}]'
C'est encore plus facile, vous pouvez simplement utiliser
JSON.stringify( Array.from(map) ); // '[["foo","bar"],["baz","quz"]]'
La solution ci-dessous fonctionne même si vous avez des cartes imbriquées
function stringifyMap(myMap) {
function selfIterator(map) {
return Array.from(map).reduce((acc, [key, value]) => {
if (value instanceof Map) {
acc[key] = selfIterator(value);
} else {
acc[key] = value;
}
return acc;
}, {})
}
const res = selfIterator(myMap)
return JSON.stringify(res);
}