Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert ES6 Map to Object Literal
let map = new Map();
map.set("a", 1);
map.set("b", 2);
map.set("c", 3);
let obj = Array.from(map).reduce((obj, [key, value]) => (
Object.assign(obj, { [key]: value }) // Be careful! Maps can have non-String keys; object literals can't.
), {});
console.log(obj); // => { a: 1, b: 2, c: 3 }
@lukehorvat

This comment has been minimized.

Copy link
Owner Author

@lukehorvat lukehorvat commented Apr 8, 2015

You can also do this inside a custom toJSON method defined for the Map instance, so that it automatically takes place whenever JavaScript's JSON.stringify function is called.

@Mike-Tran

This comment has been minimized.

Copy link

@Mike-Tran Mike-Tran commented May 9, 2018

Instead of converting the map -> array -> iterating over array / filling in new object

Could you do this?

const convertMapsToObjects = (mapInstance) => {
  const obj = {};
  for(let prop of map){
    obj[prop[0]] = prop[1];
  }
 return obj;
}

http://jsben.ch/mGhq1

Thanks for sharing!

@goldhand

This comment has been minimized.

Copy link

@goldhand goldhand commented May 25, 2018

Major performance hit when you create a new object (with Object.assign) inside every iteration.

Because you're creating a new object literal when you call Array.reduce(fn, {}), you can safely mutate that accumulator object from within the reducer function.

This is WAYYYYY faster:

let obj = Array.from(map).reduce((obj, [key, value]) => {
  obj[key] = value;
  return obj;
}, {});

Unfortunately, you'll never know because gist doesn't send comment notifications... I hope someone finds this comment and it helps them. Email me if it does, so I can be notified this helped someone 😉

@changbowen

This comment has been minimized.

Copy link

@changbowen changbowen commented Jun 4, 2018

I think with ES6 if you replace Array.from(map) with [...map.entries()], it's even faster :)
Could also be a one-liner:
let obj = [...map.entries()].reduce((obj, [key, value]) => (obj[key] = value, obj), {});

@IllusionElements

This comment has been minimized.

Copy link

@IllusionElements IllusionElements commented Jun 4, 2018

This would be the best way

  const obj = map.entries().reduce((main, [key, value]) => ({...main, [key]: value,{})
@jlyonsmith

This comment has been minimized.

Copy link

@jlyonsmith jlyonsmith commented Jun 19, 2018

@IllusionElements almost has it. reduce only exists on Array, so you have to convert the map.entries() from an iterator first. And there are some brackets missing:

const obj = Array.from(map.entries()).reduce((main, [key, value]) => ({...main, [key]: value}), {})

Will do the trick. @changbowen has the right answer too if you want to use the spread operator instead of Array.from().

@gwillz

This comment has been minimized.

Copy link

@gwillz gwillz commented Jul 23, 2018

Doing a spread operator in the loop {...main, [key]: value} is as inefficient as Object.assign() in the OP.
In contrast; obj[key] = value is simply modifying the reducer sum value, rather than recreating it on every loop.
The ES6 spread operator is indeed faster than Array.from(), but is still slower than the for of loop.

TL:DR; crude results below at 100,000 iterations of a 15 element map.

fromAssign: 1255.439ms
forOf: 109.349ms
fromReuse: 369.059ms
spreadReuse: 237.935ms
fromSpread: 4260.636ms
spreadSpread: 4094.880ms
@seromenho

This comment has been minimized.

Copy link

@seromenho seromenho commented Apr 4, 2019

With for...of

const obj = {};
for (let [key, value] of map) {
  obj[key] = value;
}
@guzmanoj

This comment has been minimized.

Copy link

@guzmanoj guzmanoj commented Dec 11, 2019

No spread & no Array.from

const newObject = theMap.keys.reduce((obj, key) => {
                  obj[key] = theMap.get(key);
                  return obj;
                }, {});
@varoot

This comment has been minimized.

Copy link

@varoot varoot commented Jan 31, 2020

You can also use forEach method

const obj = {};
map.forEach((value, key) => (obj[key] = value));
@varoot

This comment has been minimized.

@broofa

This comment has been minimized.

Copy link

@broofa broofa commented Feb 22, 2020

@varoot provided the secret sauce.

const obj = Object.fromEntries(map.entries());
@varoot

This comment has been minimized.

Copy link

@varoot varoot commented Feb 23, 2020

But note that Object.fromEntries is ES2019 so it's not technically "ES6" and might need additional polyfill for Node or browsers.

@varoot provided the secret sauce.

const obj = Object.fromEntries(map.entries());
@lsironic

This comment has been minimized.

Copy link

@lsironic lsironic commented Mar 4, 2020

@varoot

const obj = {};
map.forEach((value, key) => (obj[key] = value));

no need to return anything in forEach.
map.forEach((value, key) => {obj[key] = value});

@leebenson

This comment has been minimized.

Copy link

@leebenson leebenson commented Apr 10, 2020

In Node 12+, just Object.fromEntries(map).

@snowyu

This comment has been minimized.

Copy link

@snowyu snowyu commented Jul 21, 2020

Need to think about recurisive map:

const m = new Map()
m.set('submap', new Map())
@snowyu

This comment has been minimized.

Copy link

@snowyu snowyu commented Jul 21, 2020

export function fromMap(map) {
  return Array.from
    ( map.entries()
    , ([ k, v ]) =>
        v instanceof Map
          ? { _mK: k, _mVal: fromMap (v) }
          : { _mK: k, _mVal: v }
    )
}

export function toMap(arr) {
  let m = new Map()
  arr.forEach(item => {
    let v = item._mVal;
    if (Array.isArray(v) && v[0] && v[0]._mK !== undefined) v = toMap(v)
    m.set(item._mK, v)
  })
  return m
}
@marcusflat

This comment has been minimized.

Copy link

@marcusflat marcusflat commented Aug 8, 2020

function fromMap(map) {
  let obj = {}
  for(let[k,v] of map) {
      v instanceof Map 
        ? obj[k] = fromMap(v)
        : obj[k] = v
  }
  return obj
}
@snowyu

This comment has been minimized.

Copy link

@snowyu snowyu commented Aug 9, 2020

@marcusflat: It can not reverse the object to map if so.

@marcusflat

This comment has been minimized.

Copy link

@marcusflat marcusflat commented Aug 10, 2020

@marcusflat: It can not reverse the object to map if so.

function toMap(obj) {
  let map = new Map()
  for(let k of Object.keys(obj)) {
      obj[k] instanceof Object 
        ? map.set(k, toMap(obj[k]))
        : map.set(k, obj[k]);
  }
  return map
}
@snowyu

This comment has been minimized.

Copy link

@snowyu snowyu commented Aug 12, 2020

@marculsflat: your scene is that all object are the Map. but not all objects are the map in some scene.

treeMap =  {
'filepath': {
  name: 'filebasename',
  path: 'filepath',
  stat: new Stat(), // not map
  children: new Map(...)
}
@xgqfrms

This comment has been minimized.

Copy link

@xgqfrms xgqfrms commented Oct 1, 2020

ES6 ways

  1. Object.fromEntries
const log = console.log;

const map = new Map();
// undefined
map.set(`a`, 1);
// Map(1) {"a" => 1}
map.set(`b`, 2);
// Map(1) {"a" => 1, "b" => 2}
map.set(`c`, 3);
// Map(2) {"a" => 1, "b" => 2, "c" => 3}

// Object.fromEntries ✅
const obj = Object.fromEntries(map);

log(`\nobj`, obj);
// obj { a: 1, b: 2, c: 3 }
  1. ...spread & destructing assignment
const autoConvertMapToObject = (map) => {
  const obj = {};
  for (const item of [...map]) {
    const [
      key,
      value
    ] = item;
    obj[key] = value;
  }
  return obj;
}

const log = console.log;

const map = new Map();
// undefined
map.set(`a`, 1);
// Map(1) {"a" => 1}
map.set(`b`, 2);
// Map(1) {"a" => 1, "b" => 2}
map.set(`c`, 3);
// Map(2) {"a" => 1, "b" => 2, "c" => 3}

const obj = autoConvertMapToObject(map);
log(`\nobj`, obj);
// obj { a: 1, b: 2, c: 3 }
@BinodNagarkoti

This comment has been minimized.

Copy link

@BinodNagarkoti BinodNagarkoti commented May 10, 2021

Major performance hit when you create a new object (with Object.assign) inside every iteration.

Because you're creating a new object literal when you call Array.reduce(fn, {}), you can safely mutate that accumulator object from within the reducer function.

This is WAYYYYY faster:

let obj = Array.from(map).reduce((obj, [key, value]) => {
  obj[key] = value;
  return obj;
}, {});

Unfortunately, you'll never know because gist doesn't send comment notifications... I hope someone finds this comment and it helps them. Email me if it does, so I can be notified this helped someone 😉

this one helped me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment