0

I have a JavaScript object that I receive from an API that I cannot modify. I would like to use this data within a tool, but the tool only accepts values stored on the root level of the object e.g. I cannot use dot notation to access the value of a key a level down.

Based on the example below, I'd like to be able to access shape.colour, but by referencing something like shape__colour instead, from a new JSON object.

Example starting object:

[{
  "id" : 12345,
  "size" : 40,
  "shape": {
     "colour" : 'yellow',
     "dimension" : '2D'
  }
},
{
  "id" : 12346,
  "size" : 50,
  "shape": {
     "colour" : 'blue',
     "dimension" : '3D'
  }
}]

What I need it to look like:

[{
  "id" : 12345,
  "size" : 40,
  "shape__colour": 'yellow',
  "shape__dimension" : '2D;'
  }
},
{
  "id" : 12346,
  "size" : 50,
  "shape__colour": 'blue',
  "shape__dimension" : '3D'
  }
}]

Other examples of object flattening functions that I've come across seem to produce a single level array (removing the objects altogether), whereas I need to keep the individual objects, but for the data inside them to be on one level.

Any help would be greatly appreciated!

phuzi
  • 12,078
  • 3
  • 26
  • 50

2 Answers2

3

Another map function:

const result = arr.map( 
  ({shape, ...rest}) => ({ shape__colour: shape.colour, shape__dimension: shape.dimension, ...rest })
);

Or if shape has dynamic properties:

const result = arr.map(
 ({shape, ...rest}) => Object.assign(rest, ...Object.keys(shape).map(key => {["shape__"+key] : shape[key]}))
);
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • This is great, and is definitely getting me closer to the end object I need. The original data set has about 50 other "root" keys like id and size. Is there a way of looping through those and adding them to the new object without explicitly listing them all? Many thanks for your help! – techytuppers Nov 14 '17 at 14:03
  • @techytruppers try my answer please ;) it should work already like this ( thats what the `...rest` is all about) – Jonas Wilms Nov 14 '17 at 14:05
  • Oh damn.. I thought that was "add the rest here" so I removed it (facepalm). Thank you so much! – techytuppers Nov 14 '17 at 14:10
2

You can use map to return a new array with the flattened shape properties:

let result = arr.map(({id, size, shape}) => {
  return {
    id,
    size,
    shape_colour: shape.colour,
    shape_dimension: shape.dimension
  }
});

Note: you can also destructure the shape object in the arguments list:

let result = arr.map(({
  id,
  size,
  shape: { colour: shape_colour, dimension: shape_dimension }
}) => {
  return {
    id,
    size,
    shape_colour,
    shape_dimension,
  }
});
Andy
  • 61,948
  • 13
  • 68
  • 95