0

I have properties in an Array and an Object. I need to remove the properties, which are not in the Array allowedFields.

Actually, I need to create separate Object with only allowed fields from response data. Please suggest a solution.

let allowedFields = [
  "organization_id",
  "organization_name",
  "payload.offer.application_id",
  "payload.offer.user_id",
  "id",
  "candidate_id",
];

Below is the Object values:

let data = {
  organization_id: 4002400004,
  organization_name: "Velocity Global Integration Sandbox",
  action: "offer_updated",
  payload: {
    offer: {
      id: 4524843004,
      application_id: 31948577004,
      user_id: 4123647004,
      version: 1,
      sent_on: null,
      resolved_at: "2022-05-19T06:21:25.084Z",
      start_date: "2022-05-17",
      notes: null,
      job_id: 4298940004,
      offer_status: "Accepted",
    },
    resume: {
      name: "manikandan",
    },
  },
};

Object only have the properties which exists in the allowedFields Array. Expecting output below:

let output = {
  organization_id: 4002400004,
  organization_name: "Velocity Global Integration Sandbox",
  payload: {
    offer: {
      application_id: 31948577004,
      user_id: 4123647004,
    },
  },
};
Adam Orłowski
  • 4,268
  • 24
  • 33
  • 1
    Use `JSON.stringify` and `JSON.parse` with a reviver that checks your whitelist – Bergi May 27 '22 at 09:15
  • Shouldn't there be an `id` in your expected output? It's in the `allowedFields` but seems to have been removed? – DBS May 27 '22 at 09:18
  • @DBS some typing mistake, now i have edited. actually its should allow payload.offer.application and payload.offer.user_id only in offer object – mani kandan May 27 '22 at 09:22
  • If you are okay using lodash, you can use the _.pick method to get only the required properties. See this [link](https://stackoverflow.com/questions/40329742/removing-object-properties-with-lodash) for further info. – CodeNinja May 27 '22 at 09:49

2 Answers2

4

Approach 1

  1. Loop over all the paths in the allowedPaths array.

  2. Split the path by . to obtain an array of keys.

  3. Then loop over the array of keys and for every key fill in the resData object using actual data object.

const 
  allowedPaths = ["organization_id","organization_name","payload.offer.application_id","payload.offer.user_id","id","candidate_id"],
  data = {organization_id:4002400004,organization_name:"Velocity Global Integration Sandbox",action:"offer_updated",payload:{offer:{id:4524843004,application_id:31948577004,user_id:4123647004,version:1,sent_on:null,resolved_at:"2022-05-19T06:21:25.084Z",start_date:"2022-05-17",notes:null,job_id:4298940004,offer_status:"Accepted"},resume:{name:"manikandan"}}};

function filterData(data, allowedPaths) {
  const resData = {};
  allowedPaths.forEach((path) => {
    const pathArr = path.split(".");
    let actualDataObj = data;
    let resultantObj = resData;
    let toDetach;
    for (let i = 0; i < pathArr.length; i++) {
      const k = pathArr[i];
      if (!actualDataObj?.hasOwnProperty(k)) {
        if (toDetach) {
          delete toDetach.object[toDetach.key];
        }
        return;
      }
      if (i === pathArr.length - 1) {
        resultantObj[k] = actualDataObj[k];
      } else if (!resultantObj.hasOwnProperty(k)) {
        resultantObj[k] = {};
        if (!toDetach) {
          toDetach = { object: resultantObj, key: k };
        }
      }
      resultantObj = resultantObj[k];
      actualDataObj = actualDataObj[k];
    }
  });
  return resData;
}

console.log(filterData(data, allowedPaths));

Approach 2

You can also recursively loop over all the properties in the data object and create an object with the allowed properties.

const 
  allowedPaths = ["organization_id","organization_name","payload.offer.application_id","payload.offer.user_id","id","candidate_id"],
  data = {organization_id:4002400004,organization_name:"Velocity Global Integration Sandbox",action:"offer_updated",payload:{offer:{id:4524843004,application_id:31948577004,user_id:4123647004,version:1,sent_on:null,resolved_at:"2022-05-19T06:21:25.084Z",start_date:"2022-05-17",notes:null,job_id:4298940004,offer_status:"Accepted"},resume:{name:"manikandan"}}};

function filterData(data, allowedPaths, parentPath = "") {
  return Object.entries(data).reduce((o, [k, v]) => {
    const path = `${parentPath ? parentPath + "." : ""}${k}`;
    if (allowedPaths.has(path)) {
      return { ...o, [k]: v };
    }
    if (v && typeof v === "object") {
      const subObj = filterData(v, allowedPaths, path);
      if (Object.keys(subObj).length) {
        return { ...o, [k]: subObj };
      }
    }
    return o;
  }, {});
}

console.log(filterData(data, new Set(allowedPaths)));

Note: Both the above solutions also handle scenarios where invalid paths are present in the allowedPaths array. Here are some invalid paths:

  • "id"
  • "payload.offer.application_id.value"
  • "foo.bar.baz"

Relevant documentations:

SSM
  • 2,855
  • 1
  • 3
  • 10
0

Can you try this.

function CheckKey(obj, keyVal, allowedFields) {
    Object.keys(obj).forEach(function (key) {
        let keyValInternal = keyVal.length === 0 ? key : keyVal + '.' + key;

        if (typeof obj[key] === 'object') {
              return CheckKey(obj[key], keyValInternal, allowedFields);
        } else {
          if (allowedFields.indexOf(keyValInternal) < 0){
              delete obj[key];
          }  
        }
    });
}

I ran this on a simple set of data (example below) and it stripped out the "b" parameter

let x = {t: {a:1, b:2}, s: 3}

let allowedFields = [
  "t.a"
];

CheckKey(x, '', allowedFields);

console.log(x)

Output

{
    "t": {
        "a": 1
    }
}
Melroy Coelho
  • 212
  • 2
  • 6
  • i couldnt console the response, in the CheckKey function value is not returned – mani kandan May 27 '22 at 09:40
  • This answer has a typo and also doesn't appear to work for nested properties as defined in allowedFields. – Yogi May 27 '22 at 09:45
  • Modified it as I posted my answer when the original requirement didn't have the nested conditions in there. But it should work now with your original list. – Melroy Coelho May 27 '22 at 10:00
  • Fails when a field has a null value as in the test data. "Uncaught TypeError: Cannot convert undefined or null to object" – Yogi May 27 '22 at 10:13