Home > Enterprise >  Create nested object from serializeArray
Create nested object from serializeArray

Time:03-02

I'd like to create this structure:

{
    "officine_type": "Pharmacie",
    "officine_value": 2002626,
    "declared_lines": [
                          {
                             "ean": 3578835501148,
                             "qty": 1
                           },
                           {
                             "ean": 3578835502671,
                             "qty": 2
                           }
                       ],
    "other_value": "my other value"
}

From a serializeArray() with this output:

0: {name: 'declared_lines.0.ean', value: '3578835502244'}
1: {name: 'declared_lines.0.qty', value: '4'}
2: {name: 'declared_lines.1.ean', value: '3578835502220'}
3: {name: 'declared_lines.1.qty', value: '1'}
4: {name: 'declared_lines.2.ean', value: ''}
5: {name: 'declared_lines.2.qty', value: '0'}
6: {name: 'officine_type', value: 'Pharmacy'}
7: {name: 'officine_value', value: '2000461'}
8: {name: 'other_value', value: ''}

I'm struggling on how to push sub-objects in declared_lines

Right now i have this:

let formData = form.serializeArray();

  for (let i = 0; i < formData.length; i  ) {
    if (formData[i]['name'].indexOf('declared_lines') !== 1) {
      let inputName = formData[i]['name'].split('.');
      let namespace = inputName[0];
      let n = inputName[1];
      let key = inputName[2];
      let subObj = {};
      let current = 'declared_lines[' i ']';
      let previous = 'declared_lines[' (i-1) ']';

      if (obj.hasOwnProperty(namespace) === false) {
        obj[namespace] = [];
      }
    }
    obj[formData[i]['name']] = formData[i]['value'];
  }

My brain won't go further :(

CodePudding user response:

You could take the name and split it by dot for the path of the new object and the value and build a new object with the given information.

In setValue, the reduce callback checks if the next key is a stringed numerical value and takes an array as default object instead of an object.

function setValue(object, path, value) {
    const last = path.pop();

    path
        .reduce((o, k, i, kk) => o[k] = o[k] || (isFinite(i   1 in kk ? kk[i   1] : last) ? [] : {}), object)
        [last] = value;

    return object;
}

const
    data = [{ name: 'declared_lines.0.ean', value: '3578835502244' }, { name: 'declared_lines.0.qty', value: '4' }, { name: 'declared_lines.1.ean', value: '3578835502220' }, { name: 'declared_lines.1.qty', value: '1' }, { name: 'declared_lines.2.ean', value: '' }, { name: 'declared_lines.2.qty', value: '0' }, { name: 'officine_type', value: 'Pharmacy' }, { name: 'officine_value', value: '2000461' }, { name: 'other_value', value: '' }],
    result = data.reduce(
        (object, { name, value }) => setValue(object, name.split('.'), value),
        {}
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

Object destructuring and array.reduce can make your code more readable, try:

let formData = [
   {name: 'declared_lines.0.ean', value: '3578835502244'},
   {name: 'declared_lines.0.qty', value: '4'},
   {name: 'declared_lines.1.ean', value: '3578835502220'},
   {name: 'declared_lines.1.qty', value: '1'},
   {name: 'declared_lines.2.ean', value: ''},
   {name: 'declared_lines.2.qty', value: '0'},
   {name: 'officine_type', value: 'Pharmacy'},
   {name: 'officine_value', value: '2000461'},
   {name: 'other_value', value: ''}
];

let output = formData.reduce((acc,cur) => {
   let { name, value } = cur;
   if(name.indexOf('declared_lines') === -1){
      acc[name] = value;
   } else {
      let [namespace, n, key] = name.split('.');
      if(!acc[namespace]) acc[namespace] = [];
      if(!acc[namespace][n]) acc[namespace][n] = {};
      acc[namespace][n][key] = value;
   }
   return acc;
}, {});

console.log(output);

In this case reduce starts with an empty object and it loops over your array to process each element (cur).

  • Related