Maximus Maximus - 5 months ago 12
Javascript Question

How to write a function that inlines object properties

I have the following object:

var ob = {
view: {
name: 'zpo',
params: {
taskId: 3,
zuka: 'v'
}
}
}


I need to have this object in the following form:

{
"view.name":"zpo",
"view.params.taskId":3,
"view.params.zuka":"v"
}


I have written a function that can do that, but the problem is that it requires external variables passed to it. Here is this function:

function inline(o, result, container) {
for (var p in o) {
if (typeof o[p] === "object") {
inline(o[p], result.length > 0 ? result+'.'+p : p, container);
} else {
container[result + '.' + p] = o[p];
}
}
}

var ob = {
view: {
name: 'zpo',
params: {
taskId: 3,
zuka: 'v'
}
}
}

var c = {};
var r = inline(ob, '', c);


Is there any way to write this function to return correct result without the need to pass
result
and
container
external variables?

Answer

Here is a version that does not require any parameters.

// Return an array containing the [key, value] tuples of an object.
const objEntries = o => Object.keys(o).map(k => [k, o[k]]);

const inline = (o) => objEntries(o).reduce((result, [key, val]) => {
  if(val instanceof Object){
    objEntries(inline(val))
      .forEach(([subK, subVal]) => result[key + '.' + subK] = subVal);
  } else {
    result[key] = val;
  }
  return result;
}, {});

var ob = {
    view: {
        name: 'zpo',
        params: {
            taskId: 3,
            zuka: 'v'
        }
    }
}

var r = inline(ob);
console.log(r);

I used arrow functions and destructuring. Old browsers won't support it. If you need to support them, just replace the arrow functions with regular functions and manually destructure the arguments.