javascriptarraysjsonobjectserializearray

Create nested object from serializeArray


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 :(


Solution

  • 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] ??= (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; }