Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

121
Vistas
Generate nesting object by path

I want to make function which takes object path, for example

{ 'person.data.info.more.favorite': 'smth' }

and returns nested object:

{
  person: {
    data: {
      info: {
        more: {
          favorite: 'smth',
        },
      },
    },
  },
}

What's the most simple method to do it?

about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

If you only need to do a single key/value pair, a straightforward solution of nest using split and reduceRight -

const nest = ([path, value]) =>
  path.split('.').reduceRight((v, p) => ({ [p]: v }), value)

console.log(nest(['a', 'smth']))
console.log(nest(['a.b', 'smth']))
console.log(nest(['person.data.info.more.favorite', 'smth']))

{
  "a": "smth"
}
{
  "a": {
    "b": "smth"
  }
}
{
  "person": {
    "data": {
      "info": {
        "more": {
          "favorite": "smth"
        }
      }
    }
  }
}

If you need to apply this to an entire object where the key paths could possibly overlap with each other, we can write expand which depends on nest -

const input = {
  "server.host": "localhost",
  "server.port": 9999,
  "database.host": "localhost",
  "database.name": "mydb",
  "database.port": 7777,
  "database.user": "root",
  "debug.log": true
}

console.log(expand(input))
{
  "server": {
    "host": "localhost",
    "port": 9999
  },
  "database": {
    "host": "localhost",
    "name": "mydb",
    "port": 7777,
    "user": "root"
  },
  "debug": {
    "log": true
  }
}

We can write expand(o) to take Object.entries from the input object o and .map(nest) over each, and finally .reduce(merge) the result -

const expand = o =>
  Object.entries(o).map(nest).reduce(merge, {})

const nest = ([path, value]) =>
  path.split(".").reduceRight((v, p) => ({ [p]: v }), value)

const merge = (left = {}, right = {}) =>
  Object
    .entries(right)
    .map(([ k, v ]) =>
      isobject(v) && isobject(left[k])
        ? [ k, merge(left[k], v) ]
        : [ k, v ]
    )
    .reduce(assign, left)
      
const assign = (o, [ k, v ]) =>
  Object.assign(o, { [k]: v })

const isobject = t =>
  t?.constructor === Object   
    
const input = {
  "server.host": "localhost",
  "server.port": 9999,
  "database.host": "localhost",
  "database.name": "mydb",
  "database.port": 7777,
  "database.user": "root",
  "debug.log": true
}

console.log(expand(input))

about 4 years ago · Juan Pablo Isaza Denunciar

0

EDIT: Here is the correct answer sorry I misread it the first time.

let myObj = { 'person.data.info.more.favorite': 'smth' }

function getNestedObj( object ) {

  let keys = Object.keys( object )[0];
  let value = Object.values( object )[0];
  let keyArray = keys.split(".");

  let nextObject;
  let returnObj = {};
  

  keyArray.forEach( ( key ) => {
 
    let newObj = {};

    if( !nextObject ) {
      returnObj[key] = newObj
      nextObject = newObj;
    } else {
      nextObject[key] = newObj
      nextObject = newObj;
    }
    console.log(key)
  });

  nextObject[0] = value

  console.log( returnObj );

  return returnObj;
}

getNestedObj( myObj);

OLD ANSWER THAT READ QUESTION WRONG:

Hey you can accomplish this with the below code. It will only work with string values though with this implementation

"use strict";
let myObject = {
    person: {
        data: {
            info: {
                more: {
                    favorite: 'smth',
                },
                less: {
                    favourite: 'smthing else'
                },
                random: "a string"
            },
        },
    },
};
function concatKeys(object, key) {
    let keys = Object.keys(object);
    let keyDictionary = {};
    if (key && typeof object === 'string') {
        return { [key]: object };
    }
    if (keys.length > 0) {
        keys.forEach((nextKey) => {
            let newKey = key ? `${key}.${nextKey}` : nextKey;
            let nextObj = object[nextKey];
            let newDictionary = concatKeys(nextObj, newKey);
            keyDictionary = Object.assign(Object.assign({}, keyDictionary), newDictionary);
        });
    }
    return keyDictionary;
}
let output = concatKeys(myObject);
console.log(output);

You can see it working here Typescript playground

Running the above code will log this to the console.

[LOG]: {
  "person.data.info.more.favorite": "smth",
  "person.data.info.less.favourite": "smthing else",
  "person.data.info.random": "a string"
} 

Edit: Sorry I realize now you asked for this in javascript updated the answer to be in JS but the playground is still typescript but the above is JS.

about 4 years ago · Juan Pablo Isaza Denunciar

0

This version has a similar idea to the answer from Mulan, but with a different breakdown in responsibilities. It goes through a useful intermediate format that I've been calling pathEntries, a parallel to the result of Object.entries output, but containing full paths rather than just top-level properties. For this example, it would be just

[['person', 'data', 'info', 'more', 'favorite'], 'smth']

Our expand function calls Object .entries on your input, splits the keys on dots, and then calls hydrate on the result. hydrate is in my regular utility belt and is just a thin wrapper around setPath, folding the path entries into a single object. It looks like this:

const setPath = ([p, ...ps]) => (v) => (o) =>
  p == undefined ? v : Object .assign (
    Array .isArray (o) || Number .isInteger (p) ? [] : {},
    {...o, [p]: setPath (ps) (v) ((o || {}) [p])}
  )

const hydrate = (xs) =>
  xs .reduce ((a, [p, v]) => setPath (p) (v) (a), {})

const expand  = (o) =>
  hydrate (Object .entries (o) .map (([k, v]) => [k.split ('.'), v]))

console .log (expand ({'person.data.info.more.favorite': 'smth'}))

const input = {"server.host": "localhost", "server.port": 9999, "database.host": "localhost", "database.name": "mydb", "database.port": 7777, "database.user": "root", "debug.log": true}

console .log (expand (input))
.as-console-wrapper {max-height: 100% !important; top: 0}

One useful thing about this intermediate format is that it can also represent arrays, using integers for array indices and strings for object properties:

hydrate ([
  [[0, 'foo', 'bar', 0, 'qux'], 42], 
  [[0, 'foo', 'bar', 1, 'qux'], 43], 
  [[0, 'foo', 'baz'], 6],
  [[1, 'foo', 'bar', 0, 'qux'], 44], 
  [[1, 'foo', 'bar', 1, 'qux'], 45], 
  [[1, 'foo', 'baz'], 7],  
]) //=> 
// [
//   {foo: {bar: [{qux: 42}, {qux: 43}], baz: 6}}, 
//   {foo: {bar: [{qux: 44}, {qux: 45}], baz: 7}}
// ]

But to use that feature here, we would probably need a more sophisticated string format, something like { '[0].foo.bar[0].qux': 42 } and we'd need a somewhat more sophisticated parser than just k .split ('.'). This is not difficult, but would take us further afield, as would dealing with the still more sophisticated system that allows for arbitrary string keys, including quotation marks, brackets, and periods.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda