0

I have an object like below

{
  UserId: "",
  BidderId: "",
  "1stDomestic.BidderId": "",
  "1stDomestic.UserId": "234",
  "1stEmployee.CreatedDate": "",
  "1stIndependent.UpdatedDate": "",
  "1stIndependent.CreateDate": ""
}

The requirement is such that I need to group the dotted object keys and create the output as below

 {
  UserId: "",
  BidderId: "",
  1stDomestic: [
                 {
                   BidderId="",
                   UserId="234"
                 }
  ],
  1stEmployee: [
                 {
                   CreatedDate=""
                 }
  ],
  1stIndependent: [
                 {
                   UpdatedDate="",
                   CreatedDate=""
                 }
  ],
  lstDomestic.BidderId = "",
  1stDomestic.UserId="234",
  1stEmployee.CreatedDate="",
  1stIndependent.UpdatedDate=""
  1stIndependent.CreateDate=""
 }

I have tried to achieve this using couple of approaches. Here requestedData is the object

Approach 1

for (let prop in requestedData) {
  if (prop.indexOf(".") > -1) {
    mainKey[prop.split(".").pop()] = requestedData[prop];
    requestedData[prop.substr(0, prop.indexOf("."))] = [mainKey];
  }
}
console.log(requestedData)

The above approach gives me the structure, but the array data reflects the same for all.

      1stDomestic: [
                 {
                   BidderId="",
                   UserId="234",
                   CreatedDate="",
                   UpdatedDate=""
                 }
      ],
      1stEmployee: [
                 {
                   BidderId="",
                   UserId="234",
                   CreatedDate="",
                   UpdatedDate=""
                 }
      ],
      1stIndependent: [
                 {
                   BidderId="",
                   UserId="234",
                   CreatedDate="",
                   UpdatedDate=""
                 }
      ]

Approach 2

for (let prop in requestedData) {
  if (prop.indexOf(".") > -1) {
    arr.push({
      newProp: prop.substr(0, prop.indexOf(".")), //-->1
      mainKey: prop.split(".").pop(), // --> 2
      value: requestedData[prop] // -->3
    });
  }
}
console.log(Object.assign(requestedData, groupData(arr));

groupData(arrVal) {
 let key = "newProp";
 return resData.reduce((previous, current) => {
   previous[current[key]] && previous[current[key]].length != 0
    ? previous[current[key]].push(current)
    : (previous[current[key]] = new Array(current));
   return previous;
 }, {});
}

The above approach groups the data based on the keys, but then it creates and individual arrays of object with properties as in 1,2 and 3

I expect this to be the way as mentioned above. I am kind of now in a fix and trying to figure that out.

I am new to this forum, asking question, please bear if I somehow made this question too lengthy and intuitive. Help would be appreciated

4
  • Can the dotted keys be more than 2 levels deep? Like lstDomestic.BidderId.name. Commented Oct 18, 2019 at 4:31
  • No. It will be not 2 levels deep Commented Oct 18, 2019 at 4:32
  • 1
    In your expected output, why have you wrapped the value in an array: 1stDomestic: [{BidderId="", UserId="234"}] ? What is the point of a 1 element array? Why can't you just have an object as the value 1stDomestic: {BidderId="", UserId="234"}? Commented Oct 18, 2019 at 4:37
  • That is because the API is expecting an array of object Commented Oct 18, 2019 at 4:38

6 Answers 6

1

You can first create an object of nested objects based on the keys using reduce and then merge your original object with the nested object to get your final result:

const data = {
  UserId: "",
  BidderId: "",
  "1stDomestic.BidderId": "",
  "1stDomestic.UserId": "234",
  "1stEmployee.CreatedDate": "",
  "1stIndependent.UpdatedDate": "",
  "1stIndependent.CreateDate": ""
};

const nested = Object.entries(data)
  .filter(([k, v]) => k.includes('.'))
  .reduce((acc, [k, v]) => {
    const [parent, child] = k.split('.');
    acc[parent] = acc[parent] || [{}];
    acc[parent][0][child] = v;
    return acc;
  }, {});

const result = { ...data, ...nested};
console.log(result);

Sign up to request clarification or add additional context in comments.

Comments

0

You can use below solution.

var requestedData = {
  UserId: "",
  BidderId: "",
  "lstDomestic.BidderId" : "",
  "lstDomestic.UserId":"234",
  "lstEmployee.CreatedDate":"",
  "lstIndependent.UpdatedDate":"",
  "lstIndependent.CreateDate":""
}


var newData = [];
var previousKey = "";

for (let prop in requestedData) {

  if (prop.indexOf(".") > -1) {

        if(previousKey != prop.substr(0, prop.indexOf(".")))
    {
     ainKey = [];
    }
    previousKey = prop.substr(0, prop.indexOf("."))
    mainKey[prop.split(".").pop()] = requestedData[prop];
    newData[prop.substr(0, prop.indexOf("."))] = [mainKey];
  }
}
console.log(newData)

you can try live working demo.

https://jsfiddle.net/cakp8z6n/4/

4 Comments

I get an error running your code: mainKey is not defined
check new link.
Looks like your one is close, but it is giving arrays of array 1stDomestic:[ [ "BidderId": "" ] ]. It should be an array of object like - 1stDomestic:[ { "BidderId": "" } ]
mainKey = {}, instead of []
0

If you call your original object obj, this should work:

Object.keys(obj).forEach(key => {
    if (key.includes('.')) {
        const [base, suffix] = key.split('.');
        obj[base] = obj[base] || [{}];
        obj[base][0][suffix] = obj[key];
    }
});

console.log(obj);

Or, if you don't want to modify the original object, but make a modified copy instead:

const obj2 = {};

Object.keys(obj).forEach(key => {
    obj2[key] = obj[key];

    if (key.includes('.')) {
        const [base, suffix] = key.split('.');
        obj2[base] = obj2[base] || [{}];
        obj2[base][0][suffix] = obj[key];
    }
});

Comments

0
let orgObj={
  UserId: "",
  BidderId: "",
  "lstDomestic.BidderId": "",//difference 1st and Ist
  "1stDomestic.UserId": "234",//difference 1st and Ist
  "1stEmployee.CreatedDate": "",
  "1stIndependent.UpdatedDate": "",
  "1stIndependent.CreateDate": ""
};

let complexKeys = Object.keys(orgObj).filter(key=>{return key.match(/.+\..+/)})

So complexKeys now ["lstDomestic.BidderId", "1stDomestic.UserId", "1stEmployee.CreatedDate", "1stIndependent.UpdatedDate", "1stIndependent.CreateDate"]

complexKeys.forEach(eachCompleKey=>{debugger;

  let firstPart= eachCompleKey.match(/^(\w+)\./)[1];
  let lastPart= eachCompleKey.match(/\.(\w+)$/)[1];
  if(orgObj[firstPart]==undefined){debugger;
  orgObj[firstPart]=[{}];
  }
  orgObj[firstPart][0][lastPart]=orgObj[eachCompleKey]

})

console.log(orgObj)

Output

{
     "UserId": "",
     "BidderId": "",
     "lstDomestic.BidderId": "",
     "1stDomestic.UserId": "234",
     "1stEmployee.CreatedDate": "",
     "1stIndependent.UpdatedDate": "",
     "1stIndependent.CreateDate": "",
     "lstDomestic": [
          {
               "BidderId": ""
          }
     ],
     "1stDomestic": [
          {
               "UserId": "234"
          }
     ],
     "1stEmployee": [
          {
               "CreatedDate": ""
          }
     ],
     "1stIndependent": [
          {
               "UpdatedDate": "",
               "CreateDate": ""
          }
     ]
}

Comments

0

You can try something like below.

let obj = {
  UserId: "",
  BidderId: "",
  "lstDomestic.BidderId": "",
  "1stDomestic.UserId": "234",
  "1stEmployee.CreatedDate": "",
  "1stIndependent.UpdatedDate": "",
  "1stIndependent.CreateDate": ""
};



const res = Object.keys(obj).reduce((acc, mainKey) => {
  let [key1, key2] = mainKey.split(".");
  if (key2 && acc[key1]) {
    acc[key1][0] = { ...acc[key1][0],
      ...{
        [key2]: obj[mainKey]
      }
    }
  } else if (key2) {
    acc[key1] = [{
      [key2]: obj[mainKey]
    }];
  } else {
    acc[key1] = obj[key1];
  }
  return acc;
}, {})

const finalResult = { ...obj,
  ...res
};

console.log(finalResult)

Comments

0

So this code will do it, but I'm confused why you want it in this format. It seems like it would make more sense to have 1stDomestic, 1stEmployee, and 1stIndependent be their own objects rather than single element arrays. It just requires you to do more work later to access the data!

var requestedData = {
  UserId: "",
  BidderId: "",
  "lstDomestic.BidderId" : "",
  "lstDomestic.UserId":"234",
  "lstEmployee.CreatedDate":"",
  "lstIndependent.UpdatedDate":"",
  "lstIndependent.CreateDate":""
}

let output = {};
for (let prop in requestedData) {
  // Check to see if this is a "blah.thing" property
  if (prop.includes(".")) {
    let props = prop.split(".");
    // Check to see if we've added the array already
    if (output[props[0]])
      output[props[0]][0][props[1]] = requestedData[prop];
    else
      // ES 2015 baby!
      output[props[0]] = [{[props[1]]: requestedData[prop]}]
  }
  // If it's not then just add it normally
  else
    output[prop] = requestedData[prop];	
}
console.log(output);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.