3

I want to convert an es6 nested Map to an object.

I tried this code:

 mapToObjectRec(m) { let lo = {} for(let[k,v] of m) { if(v instanceof Map) { lo[k] = this.mapToObjectRec(v) } else { lo[k] = v } } return lo } 

I want to do the opposite of this function:

export declare type IElementsMap = Map<string, IElements>; deserializeElements(json: any): IElementsMaps | any { const elementsMap = new Map<string, IElementsMap>(); if (Array.isArray(json)) { json.forEach(outer => { const elementMap = new Map<string, IElements>(); outer[1].forEach(inner => { elementMap.set(inner[0], inner[1]); }); elementsMap.set(outer[0], elementMap); }); return elementsMap; } return json; } 

I want to send converted data inside payload request (Post request).

5
  • 2
    Because Map instances can use keys of any type, it's not always possible to convert a Map to a plain object, at least not without some mechanism for constructing string property names (or Symbols I guess). Commented Aug 22, 2019 at 14:08
  • Also you did not mention what exactly is wrong with your existing code. Commented Aug 22, 2019 at 14:11
  • 1
    Is this in JavaScript or TypeScript? Commented Aug 22, 2019 at 14:15
  • 1
    stop confusing yourself: json.forEach(...) makes you think json is an array, but JSON is always a string. If your variable is an array of elements, name it elems or something. Commented Aug 22, 2019 at 14:19
  • You should provide an example of the input and expected output. The answer of the question relies on your input types. Commented Aug 22, 2019 at 14:20

2 Answers 2

3

If the Map's keys are numbers, strings, or symbols, the following technique will work -

const m = new Map ( [ [ 'a', 1 ] , [ 'b', 2 ] , [ 'c' , new Map ( [ [ 'd', 3 ] , [ 'e', 4 ] , [ 'f' , new Map ([[ 'g', 6 ]]) ] ] ) ] ] ) const toObject = (map = new Map) => Object.fromEntries ( Array.from ( map.entries() , ([ k, v ]) => v instanceof Map ? [ k, toObject (v) ] : [ k, v ] ) ) console .log (toObject (m)) // { a: 1 // , b: 2 // , c: // { d: 3 // , e: 4 // , f: { g: 6 } // } // }

Otherwise, if the Map keys are complex objects and cannot be reliably coerced into a string, you'll have to come up with another mapping that preserves the key's actual value, such as -

const m = new Map ( [ [ 'a', 1 ] , [ 'b', 2 ] , [ 'c' , new Map ( [ [ 'd', 3 ] , [ 'e', 4 ] , [ 'f' , new Map ([[ 'g', 6 ]]) ] ] ) ] ] ) const toObject = (map = new Map) => Array.from ( map.entries() , ([ k, v ]) => v instanceof Map ? { key: k, value: toObject (v) } : { key: k, value: v } ) console .log (toObject (m)) // [ { key: "a", value: 1 } // , { key: "b", value: 2 } // , { key: "c" // , value: // [ { key: "d", value: 3 } // , { key: "e", value: 4 } // , { key: "f", value: [ { key: "g", value: 6 } ] } // ] // } // ]

Sign up to request clarification or add additional context in comments.

2 Comments

The second solution works for me. Thank you @user633183
Not sure this works if maps contain arrays of maps as values.
3

If a value in the map can be an array of maps you need:

const toObject = (map = new Map) => { if (!(map instanceof Map)) return map return Object.fromEntries(Array.from(map.entries(), ([k, v]) => { if (v instanceof Array) { return [k, v.map(toObject)] } else if (v instanceof Map) { return [k, toObject(v)] } else { return [k, v] } })) } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.