26
    var map1= new Map();
    map1.set("one",1);
    var map2 = new Map();
    map2.set("two",2);
   concatMap = {};
   concatMap['one']= map1;
   concatMap['two']= map2;
 JSON.stringify(concatMap);

//outputs : "{"one":{},"two":{}}"

I also tried:

concatMap = {};
concatMap.one= map1;
concatMap.two= map2;

why am I getting the empty object instead of map 1 and map 2 when I use JSON.stringify()?

3
  • I think JSON.stringify does not yet support Maps. I would try concatMap.one = [...map1] Commented Oct 8, 2017 at 18:18
  • Also note if you have a numerical key, object would seem to be empty.
    – span
    Commented May 5, 2019 at 16:16
  • instead of adding properties to the Map object, you can normally just create an array from 'map.entries' and then stringify the array as normal (see my answer below for details)
    – Martin CR
    Commented Apr 21, 2021 at 18:12

6 Answers 6

14

This is the expected result. JSON.stringify does not recognize a Map object as anything different than a regular object, and the JSON spec itself does not have a way to properly store a Map. It just treats the map as a regular object, possibly including any own object properties set on it.

var m = new Map();

// This is not included:
m.set('test', 123);

// This would be included:
m['other'] = 456;

console.log(JSON.stringify(m));

If you are just using string keys, you could use a regular object instead of a Map.

3
  • 2
    I don't know how many hours I tried to debug my seemingly empty map. Turns out the data was always there. Any way to log map contents without looping through it?
    – span
    Commented May 5, 2019 at 16:15
  • 1
    @span Most console.log implementations will display the contents a Map. Otherwise, looping is your only option I think. Commented May 5, 2019 at 16:18
  • Thank you. Wow, that is really crappy. Why the heck can't a Map, the most natural object in the world, not be serialized into json...?
    – spyro
    Commented Nov 29, 2022 at 18:56
13

Basic solution :

First if you have

const map = new Map();

and you set values this way :

map.set('key', 'value');

Object.stringify will emit and empty object.

You can fix that this way:

const objFromMap = Object.fromEntries(map);
JSON.stringify(objFromMap);

Complex objects :

If you have a map field into an object, example:

class MyClazz {
   field = new Map();
}
const instance = new MyClazz();
instance.field.set('k', 'v');

JSON.stringify will result :

{field: {}}

to fix that, override toJSON method. You'll have :

class MyClazz {
   field = new Map();
   toJSON(): this {
      return {
          field: Object.fromEntries(this.field),
      }
   }
}
const instance = new MyClazz();
instance.field.set('k', 'v');

Then, when using JSON.stringify(instance); we'll have :

{field: {k: 'v'}}
5

With credit to Tim Brown in his blog post on the subject - when the contents of the Map object are serialisable, you can do:

  1. serialise Map to JSON:

    JSON.stringify(Array.from(map.entries()))

  2. de-serialise JSON to Map:

    new Map(JSON.parse(jsonStr))

1

As noted by others Maps arent yet supported by JSON. However 2d arrays are so one can do:

const map1= new Map().set("one",1),
           map2 = new Map().set("two",2),
           concatMap = {
              one:[...map1],
              two:[...map2]
           };

const result = JSON.stringify(concatMap);

To parse that, do:

 let {one,two} = JSON.parse(result);
 one = new Map(one),
 two = new Map(two);
1

you can use

const newMap = JSON.parse('{}');
newMap[name] = value;

and stingfy newMap. The result is pars as Map<string, string>

0

You can use map1 = {"one", 1} instead of map object.

Here's working plunker : https://plnkr.co/edit/mUP5KbTVCo0JgdlqH1qQ?p=preview

Not the answer you're looking for? Browse other questions tagged or ask your own question.