Map、便利だよね
キーと値のセットを持てるMapオブジェクト。
配列や既存のオブジェクトでは再現できないときに超便利。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map
JSONに変換してPOSTしたい
しかし、これをバックエンドにPOSTするためにJSONに変換するときにひと悶着起きる。
var map = new Map();
map.set('hoge','value1');
map.set('fuga','value2');
JSON.stringify(map);
// '{}' からっぽ!
これは以下のようにすることで解決できる
var map = new Map();
map.set('hoge','value1');
map.set('fuga','value2');
JSON.stringify(Object.fromEntries(map));
// '{"hoge":"value1","fuga":"value2"}'
なお、JSON.stringify([...map]);
でもJSON出力は可能だが、{'hoge', 'value1'}
という形式になってしまうので変換後に扱いにくい。
階層化したMapオブジェクトで躓く
しかしここで、Mapの値にMapがある場合やオブジェクト配列内に存在するMapという状況が発生するとややこしくなる。
var map1 = new Map();
var map2 = new Map();
map1.set('hoge','value1');
map1.set('fuga','value2');
map2.set('hogehoge','value3');
map2.set('fugafuga','value4');
map2.set('piyo', map1);
JSON.stringify(Object.fromEntries(map2));
// '{"hoge":"value1","fuga":"value2","piyo":{}}' piyoがからっぽ!
var obj = {
name: 'hoge',
maps: map2
};
// JSON.stringify(Object.fromEntries(obj)); // MAPじゃないのでエラー
JSON.stringify(obj);
// '{"name":"hoge","maps":{}}' 当然Mapはからっぽ!
JSON.stringifyのreplacerを使う
replacerを使って型チェックを行い、MapオブジェクトならObject.fromEntries
をかけてやる。
function replacer(key, value) {
if (value instanceof Map) {
return Object.fromEntries(value);
} else {
return value;
}
}
JSON.stringify(map2, replacer);
/*
{
"hogehoge": "value3",
"fugafuga": "value4",
"piyo": {
"hoge": "value1",
"fuga": "value2"
}
}
*/
JSON.stringify(obj, replacer);
/*
{
"name": "hoge",
"maps": {
"hogehoge": "value3",
"fugafuga": "value4",
"piyo": {
"hoge": "value1",
"fuga": "value2"
}
}
}
*/
階層が3つ、4つとなっても問題なく変換できるので、これをバックエンドにPOSTしてやれば良い。