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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:49:39  来源:igfitidea点击:

How do you JSON.stringify an ES6 Map?

javascriptjsondictionaryecmascript-6

提问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.stringifyJSON.parse支持第二个参数。replacerreviver分别。使用下面的替换器和恢复器,可以添加对本机 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);
}