skip to Main Content

I have a an Object and I need to delete all the "id" attributes inside at every deep level except for some of them.

I did this function:

const removeFieldFromObject = ({ obj, fieldName, ignoreFields = [] }) => {
  if (typeof obj !== "object" || obj === null) {
    return obj;
  }

  if (Array.isArray(obj)) {
    for (var i = 0; i < obj.length; i++) {
      obj[i] = removeFieldFromObject({ obj: obj[i], fieldName, ignoreFields });
    }
  } else {
    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        if (prop === fieldName && !ignoreFields.includes(obj[prop])) {
          delete obj[prop];
        } else {
          obj[prop] = removeFieldFromObject({
            obj: obj[prop],
            fieldName,
            ignoreFields,
          });
        }
      }
    }
  }
  return obj;
};

If i invoke it with this object in the following way:

const obj = {
  id:1,
  data:{
    id:2,
    cards:{
      id:123,
      name:"my name",
      document:{
        id:2,
        url:"my url"
      }
    }
  }
}

const formattedObj = removeFieldFromObject({obj, fieldName: "id", ignoreFields: ["document"]})

It deletes the "id" attribute at all levels

I want it do remove all the attributes "id" except for document objects. This method removes them at every level. The reason is the condition on ignoreFields that is always true when it goes inside the document object and it checks the actual props. I looked around and found many similar questions but not with optional attributes.

Do you have any suggestion? I accept also solutions with lodash or similar.

2

Answers


  1. Could be something like this:

    const removeFieldFromObject = ({obj, fieldName, ignoreFields}) => {
    
      if(Array.isArray(obj)) {
        arr.forEach(item => removeFieldsFromObject({obj, fieldName, ignoreFields}));
        return;
      }
      if(!Object.prototype.isPrototypeOf(obj)){
        return;
      }
      delete obj[fieldName];
      
      for(const k in obj){
        ignoreFields.includes(k) || removeFieldFromObject({obj: obj[k], fieldName, ignoreFields});
      }
    };
    
    removeFieldFromObject({obj, fieldName: "id", ignoreFields: ["document"]})
    
    console.log(obj);
    <script>
    const obj = {
      id:1,
      data:{
        id:2,
        cards:{
          id:123,
          name:"my name",
          document:{
            id:2,
            url:"my url"
          }
        }
      }
    }
    </script>
    Login or Signup to reply.
  2. if (prop === fieldName && !ignoreFields.includes(obj[prop])) {
      delete obj[prop];
    } else {
      obj[prop] = removeFieldFromObject(…);
    }
    

    This doesn’t make a lot of sense – or at least, it doesn’t match how you are calling the function. It checks for the value of the property to delete in the ignoreFields. What you actually want is to check the property name before doing the recursive call, so that nothing in .document does get visited:

    if (prop === fieldName) {
      delete obj[prop];
    } else if (!ignoreFields.includes(prop)) {
      obj[prop] = removeFieldFromObject(…);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search