How can an object with mixed-types of nested children be converted into an array in JS?

Suppose I have an object that I’d like to convert into an array of objects, retaining the object keys as properties for each nested object.

In this simple example, any of these would work:

let data = {
  First: 'I am the danger',
  Second: 'I am the one who knocks',
  Third: 'Magnets, Bih!',
};

// Using .map and Object.keys()
let testOne = Object.keys(data).map((key) => ({ title: key, content: data[key] }));
console.log(testOne);

// Using .reduce and Object.keys()
let testTwo = Object.keys(data).reduce((acc, curr) => {
  return [...acc, { title: curr, content: data[curr] }]
}, []);
console.log(testTwo);

// Using a simple loop
let testThree = [];
for(let i in data) {
  testThree.push({ title: i, content: data[i] });
};
console.log(testThree);

Now consider a more complicated example of an object that contains an inconsistent pattern of objects and child-arrays:

let myCurrentObject = {
  Movies: {
    Comedy: {
      TopRanked: [
        {
          id: 99,
          name: 'The Interview',
          path: ['Movies', 'Comedy', 'TopRanked'],
        },
        {
          id: 100,
          name: 'Eurotrip',
          path: ['Movies', 'Comedy', 'TopRanked'],
        },
      ]
    },
    Action: [
      {
        id: 101,
        name: 'We Were Soldiers',
        path: ['Movies', 'Action'],
      },
      {
        id: 102,
        name: 'The Bell',
        path: ['Movies', 'Action'],
      },
    ]
  },
  Life: {
    Financial: {
      Income: [
        {
          id: 103,
          name: 'Making Hundreds',
          path: ['Life', 'Financial', 'Income'],
        },
        {
          id: 104,
          name: 'Making Thousands',
          path: ['Life', 'Financial', 'Income'],
        },
      ]
    },
    MonthlySpent: [
      {
        id: 105,
        name: 'Just a little bit',
        path: ['Life', 'MonthlySpent'],
      },
      {
        id: 106,
        name: 'Living Large',
        path: ['Life', 'MonthlySpent'],
      },
    ]
  }
}
console.log(myCurrentObject);

And I would like to convert it to an array of objects, so the output is like so:

let myDesiredOutput = [
  {
    name: "Movies",
    obj_children: [
      {
        name: "Comedy",
        obj_children: [
          {
            name: "TopRanked",
            obj_children: [
              {
                id: 99,
                name: 'The Interview',
                path: ['Movies', 'Comedy', 'Top'],
              },
              {
                id: 100,
                name: 'Eurotrip',
                path: ['Movies', 'Comedy', 'Top'],
              },
            ],
          },
        ],
      },
      {
        name: "Action",
        obj_children: [
          {
            id: 101,
            name: 'We Were Soldiers',
            path: ['Movies', 'Action'],
          },
          {
            id: 102,
            name: 'The Bell',
            path: ['Movies', 'Action'],
          },
        ]
      }
    ]
  },
  {
    name: "Life",
    obj_children: [
      {
        name: "Financial",
        obj_children: [
          {
            name: "Income",
            obj_children: [
              {
                id: 103,
                name: 'Making Hundreds',
                path: ['Life', 'Financial', 'Income'],
              },
              {
                id: 104,
                name: 'Making Thousands',
                path: ['Life', 'Financial', 'Income'],
              },
            ]
          },
        ]
      },
      {
        name: "MonthlySpent",
        obj_children: [
          {
            id: 105,
            name: 'Just a little bit',
            path: ['Life', 'MonthlySpent'],
          },
          {
            id: 106,
            name: 'Living Large',
            path: ['Life', 'MonthlySpent'],
          },
        ]
      }
    ]
  },
];
console.log(myDesiredOutput);

I am having a hard time reaching the required outcome.
I have tried to check the typeof as I traverse through it, as in the following example, but this fails miserably:

let data = {
  Movies: {
    Comedy: {
      TopRanked: [
        {
          id: 99,
          name: 'The Interview',
          path: ['Movies', 'Comedy', 'TopRanked'],
        },
        {
          id: 100,
          name: 'Eurotrip',
          path: ['Movies', 'Comedy', 'TopRanked'],
        },
      ]
    },
    Action: [
      {
        id: 101,
        name: 'We Were Soldiers',
        path: ['Movies', 'Action'],
      },
      {
        id: 102,
        name: 'The Bell',
        path: ['Movies', 'Action'],
      },
    ]
  },
  Life: {
    Financial: {
      Income: [
        {
          id: 103,
          name: 'Making Hundreds',
          path: ['Life', 'Financial', 'Income'],
        },
        {
          id: 104,
          name: 'Making Thousands',
          path: ['Life', 'Financial', 'Income'],
        },
      ]
    },
    MonthlySpent: [
      {
        id: 105,
        name: 'Just a little bit',
        path: ['Life', 'MonthlySpent'],
      },
      {
        id: 106,
        name: 'Living Large',
        path: ['Life', 'MonthlySpent'],
      },
    ]
  }
}
function prepareTreeData(data) {
  return Object.entries(data).map(([name, value]) =>
    Object.assign(
      { name },
      name && typeof value === "object"
        ? { value: "", obj_children: this.prepareTreeData(value) }
        : { value, obj_children: [] }
    )
  );
}
console.log(prepareTreeData(data));

Having spent quite a few hours researching and trying to solve this with no success, would appreciate a suggestion on the proper way to achieve this. Tnx.

39 thoughts on “How can an object with mixed-types of nested children be converted into an array in JS?”

  1. I loved as much as you will receive carried out right here.
    The sketch is tasteful, your authored subject matter
    stylish. nonetheless, you command get bought
    an edginess over that you wish be delivering the
    following. unwell unquestionably come further formerly again since exactly the same nearly a lot
    often inside case you shield this increase.

    Reply
  2. Asking questions are in fact pleasant thing if you are not
    understanding anything fully, however this piece of writing presents fastidious understanding yet.

    Reply
  3. Greetings! I know this is kinda off topic however I’d figured I’d ask.
    Would you be interested in trading links or maybe guest writing
    a blog article or vice-versa? My blog addresses a lot of the same topics as yours and
    I think we could greatly benefit from each other.
    If you’re interested feel free to send me an e-mail.
    I look forward to hearing from you! Great blog by the way!

    Reply

Leave a Comment