Reputation: 1664
I have a JS object like this:
var tenants = {
'first': {
'name': 'first',
'expired': 1
},
'second': {
'name': 'second'
}
}
And I'd like to delete the 'expired' property of tenant 'first', should I just do this?
delete tenants['first']['expired'];
Note: this question is more specific than the question: How do I remove a property from a JavaScript object?, in that my question focuses on the 'nested' part.
Upvotes: 36
Views: 64952
Reputation: 1263
With modern JS you can simple do it this way:
const tenants = {
first: {
name: 'first',
expired: 1
},
second: {
name: 'second'
}
}
delete tenants?.first?.expired;
delete tenants?.second?.expired;
delete tenants?.third?.expired;
console.log(tenants);
By using optional chaining you're able to safely try to remove nested properties on objects that might not exist.
Check the mdn site to check browser compatibility
NOTE: Optional chaining does also works with braces
Upvotes: 0
Reputation: 1362
If you want to delete a property with a particular name in an arbitrarily deep object, I would recommend that you use a battle-tested library. You can use DeepDash, an extension to Lodash.
// Recursively remove any "expired" properties
_.eachDeep(e, (child, prop, parent, ctx):boolean => {
if (prop === 'expired') {
delete parent[prop];
return false; // per docs, this means do not recurse into this child
}
return true;
});
And if you would rather have a new copy (rather than mutating the existing object), DeepDash also has an omitDeep
function you can use that will return the new object.
Upvotes: 5
Reputation: 14625
I came up with this:
const deleteByPath = (object, path) => {
let currentObject = object
const parts = path.split(".")
const last = parts.pop()
for (const part of parts) {
currentObject = currentObject[part]
if (!currentObject) {
return
}
}
delete currentObject[last]
}
Usage:
deleteByPath({ "a" : { "b" : true }},"a.b")
Upvotes: 4
Reputation: 485
If your app is using lodash, then _.unset
is a safe way for deleting nested properties. You can specify nested keys without worrying about their existence.
let games = { 'hitman': [{ 'agent': { 'id': 47 } }] };
_.unset(games, 'hitman[0].agent.id');
_.unset(games, 'hitman[0].muffin.cupcake'); // won't break
further reading: https://lodash.com/docs/4.17.15#unset
Upvotes: 17
Reputation: 41
If you have the path of the key separated by .
, say first.expired
in your case, you can do deleteKey(tenants, 'first.expired')
:
const deleteKey = (obj, path) => {
const _obj = JSON.parse(JSON.stringify(obj));
const keys = path.split('.');
keys.reduce((acc, key, index) => {
if (index === keys.length - 1) {
delete acc[key];
return true;
}
return acc[key];
}, _obj);
return _obj;
}
let tenants = {
'first': {
'name': 'first',
'expired': 1
},
'second': {
'name': 'second'
}
};
const PATH_TO_DELETE = 'first.expired';
tenants = deleteKey(tenants, PATH_TO_DELETE);
console.log('DELETE SUCCESSFUL:', tenants);
Upvotes: 2
Reputation: 187529
If the property you want to delete is stored in a string, you can use this function
function deletePropertyPath (obj, path) {
if (!obj || !path) {
return;
}
if (typeof path === 'string') {
path = path.split('.');
}
for (var i = 0; i < path.length - 1; i++) {
obj = obj[path[i]];
if (typeof obj === 'undefined') {
return;
}
}
delete obj[path.pop()];
};
Example Usage
var tenants = {
'first': {
'name': 'first',
'expired': 1
},
'second': {
'name': 'second'
}
}
var property = 'first.expired';
deletePropertyPath(tenants, property);
Upvotes: 17
Reputation: 36594
Yes. That would work.
delete tenants['first']['expired'];
or delete tenants.first.expired;
.
If you are deleting it only because you wanted to exclude it from JSON.stringify()
, you can also just set it to undefined
, like tenants['first']['expired'] = undefined;
Upvotes: 30