0

I'm working on a project where I get an object in input like this one :

const obj = {
  a: 'somestring',
  b: 42,
  c: {
   d: 'foo',
   e: 'bar'
  },
  f: [1, 2]
};

and I need to create some variables to get to this output :

const a = "somestring"
const b = 42
const c.d = "foo"
const c.e = "bar"
const f[0] = 1
const f[1] = 2

I got a result with this code :

for (const [k1, v1] of Object.entries(obj)) {
  if (typeof v1 === "object") {
    if (Array.isArray(v1)) {
      for (const [k2, v2] of Object.entries(v1)) {
      console.log(`const ${k1}[${k2}] = ${v2}`);
    }
    } else {
      for (const [k2, v2] of Object.entries(v1)) {
      console.log(`const ${k1}.${k2} = ${v2}`);
    }
    }
  } else {
    console.log(`const ${k1} = ${v1}`);    
  }
}

But when I get an object more complex like this one :

const obj = {
  a: [
    { 
      b: 'lorem'
    },
    {
      c: 'ipsum'
    }
  ],
  d: {
    e: {
      f : 'foobar'
    }
  }
};

My output look like this :

const a[0] = [object Object]
const a[1] = [object Object]
const d.e = [object Object]

I can't find any relevant solutions. Is there a solution or npm package for this?

ragnar
  • 35
  • 5
  • why do you need this? why not take the object directly? – Nina Scholz Dec 22 '20 at 09:56
  • `with (obj) { … }`? But really, no, you should not do this. – Bergi Dec 22 '20 at 10:02
  • @NinaScholz I need to write a program that automatically generates a specific backend from a swagger file and where the user doesn't have to create the variables sent to the endpoints. I know I can create a server with the swagger editor but the architecture does not match my needs – ragnar Dec 22 '20 at 10:02
  • @ragnar "*generates a specific backend*" - are you saying you want to generate code? As text? – Bergi Dec 22 '20 at 10:04
  • @Bergi, yes, I need to create a js file for each enpoints from a swagger file. And inside eache files, a function will be automaticaly written with a axios request and variables as parameters, etc. – ragnar Dec 22 '20 at 10:09
  • Then please clarify your question, it seems neither of the answers so far generates code. You don't want to create actual variables, you want to create text. (Btw, that should be simple with a loop over the properties?) – Bergi Dec 22 '20 at 10:27
  • Why do you actually need to pass variables as arguments to that axios request? Shouldn't you just pass the complete object? It might help if you could post the code that you have so far, and the expected end result (full generated code per endpoint) - surely `[object Object]` won't be part of it? – Bergi Dec 22 '20 at 10:28

3 Answers3

1

You can do it with eval function in JS:

const obj = {
    a: 'somestring',
    b: 42,
    c: {
        d: 'foo',
        e: 'bar'
    },
    f: [1, 2]
};

var log = console.log;

for (let key in obj) {
    //log(key);
    eval(`var ${key} = obj.${key}`);
}

log(a);
log(b);
log(c);
log(f);
Nikhil Patil
  • 2,480
  • 1
  • 7
  • 20
Dee
  • 7,455
  • 6
  • 36
  • 70
1

There is a feature called destructuring docs click here

This feature as the docs say will help you create new variables from a nested object.

Taking a object which is nested you can access its leaf values and assign them directly to vars like this:

const o = { 
        a: 'a', 
        b: {
            c : 'c',
            d: {
                 e: 'e'
            }
        }
    };
    
const {a ,b : { c, d: {e} }} = o;
    
alert(a);
alert(c);
alert(e);

Edit: it works with arrays as well not objects only

Bogdan M.
  • 2,161
  • 6
  • 31
  • 53
  • Destructuring is exactly what I was thinking of, nice answer :) The only thing to mention maybe is that destructuring is an ES6 feature so it may not work on older browser without transpiling (like IE) – Dario Piotrowicz Dec 22 '20 at 11:30
  • indeed a good point - but we are in 2021 :) if you are targeting an old browser knowing how to deal with it is out of this scope of the question – Bogdan M. Dec 22 '20 at 11:34
  • 1
    well to be fair the feature seems to be pretty well adopted https://caniuse.com/?search=destructuring (except from IE lol) so yeah maybe you may not care about that too much – Dario Piotrowicz Dec 22 '20 at 11:37
0

I think you want something like this:

const obj = {
  a: 'somestring',
  b: 42,
  c: {
   d: 'foo',
   e: 'bar'
  },
  f: [1, 2]
};


const parse = (obj, prefix = '', isArray=false) => {
  Object.entries(obj).forEach(([k, v]) => {
      if (typeof v === 'object') parse(v, `${k}`, Array.isArray(v))
      else {
          const value = (typeof v === 'string') ? `"${v}"` : v;
          const before = isArray ? '[' : prefix ? '.' : '';
          const after = isArray ? ']' : '';
          console.log(`const ${prefix}${before}${k}${after} = ${value}`)
      }
  });
}

parse(obj);
dave
  • 62,300
  • 5
  • 72
  • 93