I'd like to start using ES6 Map instead 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?
You can't. The keys of a map can be anything, including objects. But JSON syntax only allows strings as keys.
Stringify a JavaScript ObjectUse the JavaScript function JSON. stringify() to convert it into a string. const myJSON = JSON. stringify(obj);
The JSON. stringify() method converts a JavaScript object or value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
You can map the data types of your business model into JSON by using the examples. Data in JSON is either an object or an array. A JSON object is an unordered collection of names and values. A JSON array is an ordered sequence of values.
Both JSON.stringify and JSON.parse support a second argument. replacer and reviver respectively. With replacer and reviver below it's possible to add support for native Map object, including deeply nested values
function replacer(key, value) {
  if(value instanceof Map) {
    return {
      dataType: 'Map',
      value: Array.from(value.entries()), // or with spread: value: [...value]
    };
  } 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);
                        You can't directly stringify the Map instance as it doesn't have any properties, but you can convert it to an array of tuples:
jsonText = JSON.stringify(Array.from(map.entries()));
For the reverse, use
map = new Map(JSON.parse(jsonText));
                        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.
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:
While there is no method provided by ecmascript yet, this can still be done using JSON.stingify if you map the Map to a JavaScript primitive. Here is the sample Map we'll use.
const map = new Map();
map.set('foo', 'bar');
map.set('baz', 'quz');
You can convert to JavaScript Object literal with the following helper function.
const mapToObj = m => {
  return Array.from(m).reduce((obj, [key, value]) => {
    obj[key] = value;
    return obj;
  }, {});
};
JSON.stringify(mapToObj(map)); // '{"foo":"bar","baz":"quz"}'
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"}]'
This is even easier, you can just use
JSON.stringify( Array.from(map) ); // '[["foo","bar"],["baz","quz"]]'
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With