Javascript 你如何 JSON.stringify 一个 ES6 Map?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29085197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you JSON.stringify an ES6 Map?
提问by rynop
I'd like to start using ES6 Mapinstead of JS objects but I'm being held back because I can't figure out how to JSON.stringify() a Map. My keys are guaranteed to be strings and my values will always be listed. Do I really have to write a wrapper method to serialize?
我想开始使用ES6 Map而不是 JS 对象,但我被阻止了,因为我无法弄清楚如何 JSON.stringify() 映射。我的键保证是字符串,我的值将始终列出。我真的必须编写一个包装方法来序列化吗?
采纳答案by Oriol
You can't.
你不能。
The keys of a map can be anything, including objects. But JSON syntax only allows strings as keys. So it's impossible in a general case.
地图的键可以是任何东西,包括对象。但是 JSON 语法只允许字符串作为键。所以在一般情况下是不可能的。
My keys are guaranteed to be strings and my values will always be lists
我的键保证是字符串,我的值将始终是列表
In this case, you can use a plain object. It will have these advantages:
在这种情况下,您可以使用普通对象。它将具有以下优点:
- It will be able to be stringified to JSON.
- It will work on older browsers.
- It might be faster.
- 它将能够被字符串化为 JSON。
- 它适用于较旧的浏览器。
- 它可能会更快。
回答by Bergi
You can't directly stringify the Mapinstance as it doesn't have any properties, but you can convert it to an array of tuples:
您不能直接对Map实例进行字符串化,因为它没有任何属性,但您可以将其转换为元组数组:
jsonText = JSON.stringify(Array.from(map.entries()));
For the reverse, use
对于相反的情况,请使用
map = new Map(JSON.parse(jsonText));
回答by Pawel
Both JSON.stringifyand JSON.parsesupport a second argument. replacerand reviverrespectively. With replacer and reviver below it's possible to add support for native Map object, including deeply nested values
双方JSON.stringify并JSON.parse支持第二个参数。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;
}
Usage:
用法:
const originalValue = new Map([['a', 1]]);
const str = JSON.stringify(originalValue, replacer);
const newValue = JSON.parse(str, reviver);
console.log(originalValue, newValue);
Deep nesting with combination of Arrays, Objects and Maps
结合数组、对象和地图的深度嵌套
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);
回答by Evan Carroll
While there is no method provided by ecmascript yet, this can still be done using JSON.stingifyif you map the Mapto a JavaScript primitive. Here is the sample Mapwe'll use.
虽然 ecmascript 还没有提供任何方法,但JSON.stingify如果您将 映射Map到 JavaScript 原语,仍然可以使用它来完成。这是Map我们将使用的示例。
const map = new Map();
map.set('foo', 'bar');
map.set('baz', 'quz');
Going to an JavaScript Object
转到 JavaScript 对象
You can convert to JavaScript Object literal with the following helper function.
您可以使用以下辅助函数转换为 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"}'
Going to a JavaScript Array of Objects
转到 JavaScript 对象数组
The helper function for this one would be even more compact
这个辅助函数会更紧凑
const mapToAoO = m => {
return Array.from(m).map( ([k,v]) => {return {[k]:v}} );
};
JSON.stringify(mapToAoO(map)); // '[{"foo":"bar"},{"baz":"quz"}]'
Going to Array of Arrays
转到数组数组
This is even easier, you can just use
这更容易,你可以使用
JSON.stringify( Array.from(map) ); // '[["foo","bar"],["baz","quz"]]'
回答by metodribic
Using spread sytaxMap can be serialized in one line:
使用spread sytaxMap 可以在一行中序列化:
JSON.stringify([...new Map()]);
and deserialize it with:
并将其反序列化:
let map = new Map(JSON.parse(map));
回答by Cody
A Better Solution
更好的解决方案
// somewhere...
class Klass extends Map {
toJSON() {
var object = { };
for (let [key, value] of this) object[key] = value;
return object;
}
}
// somewhere else...
import { Klass as Map } from '@core/utilities/ds/map'; // <--wherever "somewhere" is
var map = new Map();
map.set('a', 1);
map.set('b', { datum: true });
map.set('c', [ 1,2,3 ]);
map.set( 'd', new Map([ ['e', true] ]) );
var json = JSON.stringify(map, null, '\t');
console.log('>', json);
Output
输出
> {
"a": 1,
"b": {
"datum": true
},
"c": [
1,
2,
3
],
"d": {
"e": true
}
}
Hope that is less cringey than the answers above.
希望这比上面的答案更不令人讨厌。
回答by am0wa
Stringify a Mapinstance (objects as keys are OK):
字符串化一个Map实例(对象作为键是可以的):
JSON.stringify([...map])
or
或者
JSON.stringify(Array.from(map))
or
或者
JSON.stringify(Array.from(map.entries()))
output format:
输出格式:
// [["key1","value1"],["key2","value2"]]
回答by Imamudin Naseem
Below solution works even if you have nested Maps
即使您有嵌套的地图,以下解决方案也有效
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);
}

