JSオブジェクトの代わりに ES6 Map の使用を開始したいのですが、マップをJSON.stringify()する方法がわからないため、私は抑制されています。キーは文字列であることが保証され、値は常にリストになります。シリアライズするためにラッパーメソッドを書く必要が本当にありますか?
できません。
マップのキーは、オブジェクトを含め、何でもかまいません。ただし、JSON構文では、文字列のみをキーとして使用できます。したがって、一般的なケースでは不可能です。
キーは文字列であることが保証され、値は常にリストになります
この場合、プレーンオブジェクトを使用できます。次の利点があります。
Map
インスタンスにはプロパティがないため、直接文字列化することはできませんが、タプルの配列に変換することはできます。
jsonText = JSON.stringify(Array.from(map.entries()));
逆の場合は、
map = new Map(JSON.parse(jsonText));
両方 JSON.stringify
およびJSON.parse
は2番目の引数をサポートします。 replacer
およびreviver
。以下の置換およびリバイバーを使用すると、深くネストされた値を含むネイティブMapオブジェクトのサポートを追加できます。
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;
}
使用法:
const originalValue = new Map([['a', 1]]);
const str = JSON.stringify(originalValue, replacer);
const newValue = JSON.parse(str, reviver);
console.log(originalValue, newValue);
配列、オブジェクト、マップの組み合わせによる深いネスト
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);
Ecmascriptによって提供されるメソッドはまだありませんが、JSON.stingify
Map
をJavaScriptプリミティブにマップする場合。使用するサンプルMap
は次のとおりです。
const map = new Map();
map.set('foo', 'bar');
map.set('baz', 'quz');
次のヘルパー関数を使用して、JavaScriptオブジェクトリテラルに変換できます。
const mapToObj = m => {
return Array.from(m).reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
};
JSON.stringify(mapToObj(map)); // '{"foo":"bar","baz":"quz"}'
これのヘルパー関数はさらにコンパクトになります
const mapToAoO = m => {
return Array.from(m).map( ([k,v]) => {return {[k]:v}} );
};
JSON.stringify(mapToAoO(map)); // '[{"foo":"bar"},{"baz":"quz"}]'
これはさらに簡単です。
JSON.stringify( Array.from(map) ); // '[["foo","bar"],["baz","quz"]]'
以下のソリューションは、ネストされたマップがある場合でも機能します
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);
}