One of the easiest solutions would be, merging the nested object with parent,

_.merge(data, data.dates);

This will bring all data.dates property into data. Then delete data.dates

delete data.dates
Answer from RaR on Stack Overflow
🌐
Lodash
lodash.com › docs
Lodash Documentation
Creates a flattened array of values by running each element in collection thru iteratee and flattening the mapped results.
🌐
GitHub
github.com › lodash › lodash › issues › 2240
Flatten object to paths [feature request] · Issue #2240 · lodash/lodash
April 12, 2016 - Something I've made a couple times to solve certain nested object problems. Flattening an object into path keys: { my: { nested: { object: 'leaf' } } } // to { 'my.nested.object': 'leaf' } I find a lot of use for this when dealing with u...
Author   c-dante
🌐
GitHub
github.com › lodash › lodash › issues › 1228
Is there a functionality to flatten/deflatten an object? · Issue #1228 · lodash/lodash
May 25, 2015 - Hi there, I have the following object/array of objects: Object1: { id: 2, balance: 130, 'Issue : { 'id': 1, 'currency': 'EUR' } }``` Object2: ```json { id: 2, balance: 130, 'Issue.id': 1, 'Issue.currency': 'EUR' } Is there a way to 'defl...
Published   May 25, 2015
Author   moatazelmasry2
🌐
Dustin John Pfister
dustinpfister.github.io › 2018 › 08 › 12 › lodash_flatten
The lodash _.flatten method for flatting down a multi dimensional array | Dustin John Pfister at github pages
December 9, 2021 - Flatten can be used to flatten down an array of arrays into a single array, thus making it a method that can be thought of as a reversal of _.chunk. With that said the lodash chunk method will do the inversion of flatten which is to break an ...
🌐
GeeksforGeeks
geeksforgeeks.org › lodash-_-flatten-method
Lodash _.flatten() Method - GeeksforGeeks
September 2, 2024 - Lodash is a JavaScript library that works on the top of underscore.js. Lodash helps in working with arrays, strings, objects, numbers etc. The Lodash.flatten() method is used to flatten the array to one level deep.
🌐
GitHub
github.com › matteoantoci › lodash.flatten
GitHub - matteoantoci/lodash.flatten: Flatten / un-flatten nested objects · GitHub
A simple utility based on lodash to flatten and un-flatten nested objects/arrays.
Author   matteoantoci
🌐
TecHighness
techighness.com › home › java script flatten deeply nested array of objects into single level array
JavaScript Flatten Deeply Nested Array of Objects Into Single Level Array - TecHighness
December 26, 2022 - We can also _.find to get the member object: const _ = require("lodash"); const familyTree = [ // ... ]; const flatArray = _.flatMapDeep(familyTree, getMembers); // ...
Top answer
1 of 4
13

You can simply use the npm package flat.

import flat from 'flat';

const array = [
  {
    a: 'a',
    b: {
      bb: 'bb',
    },
    c: {
      cc1: 'cc1',
      cc: {
        ccc: 'ccc',
        ccd: 'ccd',
      },
    },
  },
  // ...
];

const flattenedArray = array.map(flat);

/*
  flattenedArray === [
    {
      a: 'a',
      b.bb: 'bb',
      c.cc1: 'cc1',
      c.cc.ccc: 'ccc',
      c.cc.ccd: 'ccd',
    },
    // ...
  ]
*/

And if you want to implement it yourself, here's my implementation of flat:

const flat = (obj, concatenator = '.') => (
  Object.keys(obj).reduce(
    (acc, key) => {
      if (typeof obj[key] !== 'object' || !obj[key]) {
        return {
          ...acc,
          [key]: obj[key],
        };
      }

      const flattenedChild = flat(obj[key], concatenator);

      return {
        ...acc,
        ...Object.keys(flattenedChild).reduce((childAcc, childKey) => ({ ...childAcc, [`{concatenator}${childKey}`]: flattenedChild[childKey] }), {}),
      };
    },
    {},
  )
);

const flattenedArray = array.map(o => flat(o));

Those solutions will work with any depth.

2 of 4
4

You can do this without lodash (or another library) by iterating over the keys of each item in the original array, checking their type, and further iterating over their internal keys, building new keys to hold the right values.

const array = [{
  id: 123,
  name: 'John',
  summary1: {
    count: 3,
    sum: 10
  },
  summary2: {
    count: 10,
    sum: 20
  }
}];


let newArray = array.map(item => {
  let newObj = {};

  Object.keys(item).forEach(key => {
    if (typeof item[key] === 'object') {
      Object.keys(item[key]).forEach(innerKey => {
        newObj[`${key}_${innerKey}`] = item[key][innerKey];
      });
    } else {
      newObj[key] = item[key];
    }
  });

  return newObj;
});

console.log(newArray);

Granted, this isn't necessarily very pretty or flexible (following your assumption of a single level deep).

Find elsewhere
Top answer
1 of 1
43

The approach below uses flatMap to flatten tags acquired through map. Finally, use the spread operator to assign the values from tag and the feature's name.

const result = _.flatMap(features, ({ name, tags }) =>
  _.map(tags, tag => ({ name, ...tag }))
);

const features = [{
    'name': 'feature1',
    'tags': [{
      'weight': 10,
      'tagName': 't1'
    }, {
      'weight': 20,
      'tagName': 't2'
    }, {
      'weight': 30,
      'tagName': 't3'
    }]
  },
  {
    'name': 'feature2',
    'tags': [{
      'weight': 40,
      'tagName': 't1'
    }, {
      'weight': 5,
      'tagName': 't2'
    }, {
      'weight': 70,
      'tagName': 't3'
    }]
  },
  {
    'name': 'feature3',
    'tags': [{
      'weight': 50,
      'tagName': 't1'
    }, {
      'weight': 2,
      'tagName': 't2'
    }, {
      'weight': 80,
      'tagName': 't3'
    }]
  }
];

const result = _.flatMap(features, ({ name, tags }) =>
  _.map(tags, tag => ({ name, ...tag }))
);

console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Here's a plain javascript solution that uses Array#reduce and Array#map with the help of Array#concat to flatten the array.

const result = features.reduce(
  (result, { name, tags }) => result
    .concat(tags.map(tag => ({ name, ...tag }))), 
  []
);

const features = [{
    'name': 'feature1',
    'tags': [{
      'weight': 10,
      'tagName': 't1'
    }, {
      'weight': 20,
      'tagName': 't2'
    }, {
      'weight': 30,
      'tagName': 't3'
    }]
  },
  {
    'name': 'feature2',
    'tags': [{
      'weight': 40,
      'tagName': 't1'
    }, {
      'weight': 5,
      'tagName': 't2'
    }, {
      'weight': 70,
      'tagName': 't3'
    }]
  },
  {
    'name': 'feature3',
    'tags': [{
      'weight': 50,
      'tagName': 't1'
    }, {
      'weight': 2,
      'tagName': 't2'
    }, {
      'weight': 80,
      'tagName': 't3'
    }]
  }
];

const result = features.reduce(
  (result, { name, tags }) => result
    .concat(tags.map(tag => ({ name, ...tag }))), 
  []
);

console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

🌐
Tabnine
tabnine.com › home page › code › javascript › lodash
lodash.flatten JavaScript and Node.js code examples | Tabnine
static async getInitialProps() { const getIssuesRes = await fetch( `https://api.github.com/search/issues?q=state:open+label:first-timers-only&sort=created&order=desc&per_page=100&access_token=${ process.env.GITHUB_TOKEN }`, { cache: 'default' } ) const issuesResJson = await getIssuesRes.json() const issues = issuesResJson.items const repoLanguagesStore = await getLanguages(issues) const languages = uniq(flatten(Object.values(repoLanguagesStore))) const languageCountStore = languages.reduce( (languageCountStore, language) => set(languageCountStore, language, 0), { [clearLanguageFilterButtonText]: issues.length } ) issues.forEach(issue => { issue.languages = repoLanguagesStore[issue.repository_url] issue.languages.forEach(language => (languageCountStore[language] += 1)) }) return { issues, languageCountStore } }
🌐
Educative
educative.io › answers › what-is-the-flattendeep-method-in-lodash
What is the _.flattenDeep() method in Lodash?
The _.flattenDeep() method in Lodash is used to recursively flatten an array, that is, to flatten all the nested arrays completely.
🌐
GitHub
github.com › lodash › lodash › issues › 3184
Flatten and unflatten objects · Issue #3184 · lodash/lodash
June 4, 2017 - * * @function * @param {Object} unflattened - the object to flatten * @param {String} [delimiter='.'] - the delimiter to be used when flattening the object * @returns {Object} - the flattened object, empty if provided object is undefined * @throws ...
Author   sahellebusch
🌐
GitHub
github.com › lodash › lodash › pull › 5869 › files
feat: flatten an object functionality by david-pilny · Pull Request #5869 · lodash/lodash
flattenObject Function The flattenObject function is a utility that recursively flattens a nested JavaScript object. It converts an object with nested properties into a single-level object with dot-separated keys representing the path to each ...
Author   lodash
🌐
Lodash
lodash.info › doc › flatten
flatten - Lodash documentation
_.flatten([1, [2, [3, [4]], 5]]); // => [1, 2, [3, [4]], 5]
🌐
JSFiddle
jsfiddle.net › asicfr › v2scrLgw
Lodash flatten object - JSFiddle - Code Playground
JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.
🌐
GeeksforGeeks
geeksforgeeks.org › lodash-_-flattendeep-and-_-flattendepth-method
Lodash _.flattenDeep() and _.flattenDepth() Method | GeeksforGeeks
September 2, 2024 - This method returns the new flattened array. ... const _ = require('lodash'); let ar = [1, [2, [3, 4, [5]]]]; let flattenArray = _.flattenDeep(ar); console.log(flattenArray);
Top answer
1 of 3
3

You can create a recursive function (getSchema) that checks if a value (val) is an object (arrays included), iterate it with _.flatMap(), and collects the keys until it hits a value which is not an object. It then joins the collected keys and returns the string.

const getSchema = (val, keys = []) =>
  _.isObject(val) ? // if it's an object or array
    _.flatMap(val, (v, k) => getSchema(v, [...keys, k])) // iterate it and call fn with the value and the collected keys
    :
    keys.join('.') // return the joined keys

const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 }

const result = getSchema(invoiceObject)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Without lodash, the main change is to use Object.entries() to get an array of [key, value] pairs, since Array.flatMap() can't iterate objects:

const getSchema = (val, keys = []) =>
  typeof val === 'object' && val !== null ? // if it's an object or array
    Object.entries(val) // get [key, value] pairs of object/array
      .flatMap(([k, v]) => getSchema(v, [...keys, k])) // iterate it and call fn with the value and the collected keys 
    :
    keys.join('.') // return the joined keys

const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 }

const result = getSchema(invoiceObject)

console.log(result)

2 of 3
1

inspired by the answer given in this post and understanding you just want to get the property-names, not values, you could do it like this. sorry, this uses plain javascript.

function flattenObjectToKeyArray(ob) {
  var toReturn = [];
  for (var prop in ob) {
    if (!ob.hasOwnProperty(prop)) continue;

    if ((typeof ob[prop]) == 'object' && ob[prop] !== null) {
      var flatObject = flattenObjectToKeyArray(ob[prop]);
      for (var idx = 0; idx < flatObject.length; idx++) {
        toReturn.push(prop + '.' + flatObject[idx]);
      }
    } else {
      toReturn.push(prop);
    }
  }
  return toReturn;
}