简体   繁体   中英

JS: convert array objects to dot string

I have nested objects in array and i want to convert them into dot notation string with javascript.

This is my data sample data for converting process.

[
  {
    property: 'name',
    children: [],
    message: 'name should not be empty',
  },
  {
    property: 'priceForm',
    children: [
      {
        property: 'priceCurrency',
        children: [],
        message: 'priceCurrency should not be empty',
      },
    ],
  },
  {
    property: 'priceForm',
    children: [
      {
        property: 'rolePrices',
        children: [
          {
            property: '0',
            children: [
              {
                property: 'markupType',
                children: [],
                message: 'markupType should not be empty',
              },
            ],
          },
        ],
      },
    ],
  },
]

Expected result is

{
  'name': 'name should not be empty',
  'priceForm.priceCurrency': 'priceCurrency should not be empty',
  'priceForm.rolePrices.0.markupType': 'markupType should not be empty',
}

You could collect the path first and then build a property.

 function getObject(array, path = '', target = {}) { array.forEach(({ property, children = [], message }) => { var temp = path + (path && '.') + property; if (children.length) { getObject(children, temp, target); return; } target[temp] = message; }); return target; } var array = [{ property: 'name', children: [], message: 'name should not be empty' }, { property: 'priceForm', children: [{ property: 'priceCurrency', children: [], message: 'priceCurrency should not be empty' }] }, { property: 'priceForm', children: [{ property: 'rolePrices', children: [{ property: '0', children: [{ property: 'markupType', children: [], message: 'markupType should not be empty' }] }] }] }], object = getObject(array); console.log(object); 

You can use recursive function to format you want.

 const data = [{ property: 'name', children: [], message: 'name should not be empty' }, { property: 'priceForm', children: [{ property: 'priceCurrency', children: [], message: 'priceCurrency should not be empty' }] }, { property: 'priceForm', children: [{ property: 'rolePrices', children: [{ property: '0', children: [{ property: 'markupType', children: [], message: 'markupType should not be empty' }] }] }] }]; let result = {}; function format(data, prefix) { prefix = prefix ? `${prefix}.` : '' let message = '' data.forEach(i => { prefix = `${prefix}${i.property}` message = i.message if (!i.children.length) { i.message && (result[prefix] = i.message) } else { let child_data = format(i.children, prefix) child_data['message'] && child_data['prefix'] && (result[`${prefix}.${child_data['prefix']}`] = child_data['message']) } prefix = '' }) return {prefix: prefix, message: message} } format(data) console.log(result) 

Here you go! Array.reduce and recursion is a good fit for this problem.

 const foo = (data, prefix = "") => data.reduce( (acc, { property, message, children }) => ({ ...acc, ...(children.length ? foo(children, `${prefix}${property}.`) : { [`${prefix}${property}`]: message }) }), {} ); const data = [ { property: "name", children: [], message: "name should not be empty" }, { property: "priceForm", children: [ { property: "priceCurrency", children: [], message: "priceCurrency should not be empty" } ] }, { property: "priceForm", children: [ { property: "rolePrices", children: [ { property: "0", children: [ { property: "markupType", children: [], message: "markupType should not be empty" }, { property: "sibling!", children: [], message: "added a sibling to the input data" } ] } ] } ] } ]; console.log(foo(data)); 

Update cleaned up a bit. Basically a one liner now 🙌 Added a sibling to the input data too

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM