Convertir mapa en objeto JavaScript

5 minutos de lectura

avatar de usuario de nixgadget
nixgadget

Así que tengo el siguiente javascript que contiene un par clave/valor para asignar una ruta anidada a un directorio.

function createPaths(aliases, propName, path) {
    aliases.set(propName, path);
}

map = new Map();

createPaths(map, 'paths.aliases.server.entry', 'src/test');
createPaths(map, 'paths.aliases.dist.entry', 'dist/test');

Ahora lo que quiero hacer es crear un objeto JSON a partir de la clave en el mapa.

Tiene que ser,

paths: {
  aliases: {
    server: {
      entry: 'src/test'
    },
    dist: {
      entry: 'dist/test'
    }
  }
}

No estoy seguro de si hay una manera lista para usar de hacer esto. Cualquier ayuda es apreciada.

  • Restaría el nombre clave de esa cadena con puntos y luego construiría un objeto a partir de lo que recopilé.

    – Sin emoticonos

    25 mayo 2016 a las 12:59

  • Odio cuando las personas no declaran variables y terminan con variables globales. Además, recuerde que ‘Es un error común llamar a un objeto JSON literal “un objeto JSON”. JSON no puede ser un objeto. JSON es un formato de cadena.’ (De W3Escuelas)

    – Cap 171

    21 de octubre de 2021 a las 1:28

avatar de usuario de wolfram77
wolframio77

Dada en MDN, fromEntries() está disponible desde Node v12:

const map1 = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);

const obj = Object.fromEntries(map1);
// { foo: 'bar', baz: 42 }

Para volver a convertir un objeto en un mapa:

const map2 = new Map(Object.entries(obj));
// Map(2) { 'foo' => 'bar', 'baz' => 42 }

  • Manten eso en mente Map puede contener claves que no son cadenas, por lo que obtendrá un resultado no deseado en, digamos, new Map([[{x: 0, y: 1}, 42]])

    – ggorlen

    24 de agosto de 2022 a las 3:10


simplemente usando formas ES6

  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 & destructuring assignment
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 autoConvertMapToObject = (map) => {
  const obj = {};
  for (const item of [...map]) {
    const [
      key,
      value
    ] = item;
    obj[key] = value;
  }
  return obj;
}

const obj = autoConvertMapToObject(map)

log(`\nobj`, obj);
// obj { a: 1, b: 2, c: 3 }

árbitros

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

https://2ality.com/2015/08/es6-mapa-json.html

Espero que esta función se explique por sí misma. Esto es lo que solía hacer el trabajo.

/*
 * Turn the map<String, Object> to an Object so it can be converted to JSON
 */
function mapToObj(inputMap) {
    let obj = {};

    inputMap.forEach(function(value, key){
        obj[key] = value
    });

    return obj;
}


JSON.stringify(returnedObject)

  • ES6 – implementación: mapToObj(inputMap) { const obj = {}; inputMap.forEach((valor, clave) =>{ obj[key] = valor; }); devolver objeto; }

    – Tejashree

    16 de julio de 2020 a las 10:12


Puede recorrer el mapa y las teclas y asignar el valor

function createPaths(aliases, propName, path) {
    aliases.set(propName, path);
}

var map = new Map(),
    object = {};

createPaths(map, 'paths.aliases.server.entry', 'src/test');
createPaths(map, 'paths.aliases.dist.entry', 'dist/test');

map.forEach((value, key) => {
    var keys = key.split('.'),
        last = keys.pop();
    keys.reduce((r, a) => r[a] = r[a] || {}, object)[last] = value;
});

console.log(object);

Avatar de usuario de IMTheNachoMan
IMTheNachoMan

Otro enfoque. Sería curioso cuál tiene un mejor rendimiento, pero jsPerf está inactivo :(.

var obj = {};

function createPaths(map, path, value)
{
	if(typeof path === "string") path = path.split(".");
	
	if(path.length == 1)
	{
		map[path[0]] = value;
		return;
	}
	else
	{
		if(!(path[0] in map)) map[path[0]] = {};
		return createPaths(map[path[0]], path.slice(1), value);
	}
}

createPaths(obj, 'paths.aliases.server.entry', 'src/test');
createPaths(obj, 'paths.aliases.dist.entry', 'dist/test');

console.log(obj);

Sin recursividad:

var obj = {};

function createPaths(map, path, value)
{
    var map = map;
    var path = path.split(".");
    for(var i = 0, numPath = path.length - 1; i < numPath; ++i)
    {
        if(!(path[i] in map)) map[path[i]] = {};
        map = map[path[i]];
    }
    map[path[i]] = value;
}

createPaths(obj, 'paths.aliases.server.entry', 'src/test');
createPaths(obj, 'paths.aliases.dist.entry', 'dist/test');
createPaths(obj, 'paths.aliases.dist.dingo', 'dist/test');
createPaths(obj, 'paths.bingo.dist.entry', 'dist/test');

console.log(obj);
var obj = {};

function createPaths(map, path, value)
{
    var map = map;
    var path = path.split(".");
    
    while(path.length > 1)
    {
        map = map[path[0]] = map[path.shift()] || {};
    }
    
    map[path.shift()] = value;
  
}

createPaths(obj, 'paths.aliases.server.entry', 'src/test');
createPaths(obj, 'paths.aliases.dist.entry', 'dist/test');
createPaths(obj, 'paths.aliases.dist.dingo', 'dist/test');
createPaths(obj, 'paths.bingo.dist.entry', 'dist/test');

console.log(obj);

  • jsPerf ha estado inactivo durante semanas.

    – evoluciónxbox

    25 mayo 2016 a las 13:31

  • En mi consola usando console.timesu código tomó, en promedio, 0.023msmientras que la respuesta aceptada tomó, en promedio, 0.137ms.

    – evolución xbox

    25 mayo 2016 a las 13:36

  • @evolutionxbox: si la recursión se reemplazara con un código secuencial (quizás necesitando un par de líneas más de código), probablemente se ejecutaría más rápido nuevamente. Menos código no significa necesariamente más rápido. 🙂

    – RobG

    25 mayo 2016 a las 21:25

  • @RobG muy cierto. Estas fueron pruebas de rendimiento muy crudas. Se realizaron alrededor de 20 “corridas” en cada uno.

    – evoluciónxbox

    25 mayo 2016 a las 22:11

  • @RobG: Lo sé, pero la recursividad es genial. :PI agregó un ejemplo sin recursividad.

    – IMTheNachoMan

    26 mayo 2016 a las 14:21

avatar de usuario de subhash dhaka
subhash dhaka

var items = {1:"apple",2:"orange",3:"pineapple"};
let map = new Map(Object.entries(items)); //object to map
console.log(map);
const obj = new Object();
map.forEach((value,key)=> obj[key]=value);  // map to object
console.log(obj);

  • jsPerf ha estado inactivo durante semanas.

    – evoluciónxbox

    25 mayo 2016 a las 13:31

  • En mi consola usando console.timesu código tomó, en promedio, 0.023msmientras que la respuesta aceptada tomó, en promedio, 0.137ms.

    – evoluciónxbox

    25 mayo 2016 a las 13:36

  • @evolutionxbox: si la recursión se reemplazara con un código secuencial (quizás necesitando un par de líneas más de código), probablemente se ejecutaría más rápido nuevamente. Menos código no significa necesariamente más rápido. 🙂

    – RobG

    25 mayo 2016 a las 21:25

  • @RobG muy cierto. Estas fueron pruebas de rendimiento muy crudas. Se realizaron alrededor de 20 “corridas” en cada uno.

    – evoluciónxbox

    25 mayo 2016 a las 22:11

  • @RobG: Lo sé, pero la recursividad es genial. :PI agregó un ejemplo sin recursividad.

    – IMTheNachoMan

    26 mayo 2016 a las 14:21

¿Ha sido útil esta solución?