Home:ALL Converter>How can I delete a key in a nested Javascript object with a dynamic number of properties and without eval?

How can I delete a key in a nested Javascript object with a dynamic number of properties and without eval?

Ask Time:2018-07-21T05:20:32         Author:Jacob S

Json Formatter

I am looking to delete a specific key from a nested Javascript object based on a list of dynamic properties. Here is an example of what I mean:

This is a sample object:

employees: [
    {
        name: "John",
        id: 1234567890,
        salary: 60000
    },
    {
        name: "Jack",
        id: 0987654321,
        salary: 55000
    }
],
location: {
    building: {
        address: "111 Main St"
    }
}

I am looking to delete the address key when I am provided an array of ['location', 'building', 'address']

When I say "dynamic" I mean that I could also be provided with an array of ['employees', 1] so I cannot rely on a set number of nested properties.

The only approach that works for me right now is to use the dreaded eval, which is not a permanent solution since the Javascript objects that I am reading are written by users.

let jsObject = ... // the object shown above
let properties = ['location', 'building', 'address']
let evalString = ''
for (let i = 0; i < properties.length; i++){
    evalString += '[\''+properties[i]+'\']'
}
eval('delete jsObject'+evalString)

What is an alternative to eval that will accomplish this same goal?

Author:Jacob S,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/51450513/how-can-i-delete-a-key-in-a-nested-javascript-object-with-a-dynamic-number-of-pr
Reuven Chacha :

This method accepts an object and an array of properties, and removes the inner most property as required\n\nfunction remove(obj, props) {\n delete props.slice(0, -1).reduce((init, curr) => init && init[curr], obj)[[...props].pop()];\n}\n",
2018-07-20T21:43:36
Mark :

You can break your array into everything except the last element, get a reference to that and the call delete on the object using the last element. You can use reduce to easily build the object reference. You need to be careful with arrays because you can't use delete without leaving an empty slot — delete doesn't change the length.\n\nHere's the basic idea:\n\n\r\n\r\nfunction deleteProp(obj, keys){\r\n let prop = keys.pop() // get last key\r\n let c = keys.reduce((a, c) => a[c], obj) // get penultimate obj\r\n if (Array.isArray(c)) c.splice(prop, 1) // if it's an array, slice\r\n else delete c[prop] // otherwise delete\r\n\r\n}\r\n\r\n// Delete address\r\nlet obj = {employees: [{name: \"John\",id: 1234567890,salary: 60000},{name: \"Jack\",id: 0987654321,salary: 55000}],location: {building: {address: \"111 Main St\"}}}\r\n\r\ndeleteProp(obj, ['location', 'building', 'address'])\r\nconsole.log(obj)\r\n\r\n//Delete employee 1\r\nobj = {employees: [{name: \"John\",id: 1234567890,salary: 60000},{name: \"Jack\",id: 0987654321,salary: 55000}],location: {building: {address: \"111 Main St\"}}}\r\n\r\ndeleteProp(obj, ['employees', 1])\r\nconsole.log(obj)\r\n\r\n//Delete employee 1 id\r\nobj = {employees: [{name: \"John\",id: 1234567890,salary: 60000},{name: \"Jack\",id: 0987654321,salary: 55000}],location: {building: {address: \"111 Main St\"}}}\r\n\r\ndeleteProp(obj, ['employees', 1, 'id'])\r\nconsole.log(obj)",
2018-07-20T21:37:24
Adam H :

Here is a sample that i'm sure could be trimmed down a bit but it explains each step and you should be able to see whats happening in it:\n\n\r\n\r\nlet jsObject = {\r\n employees: [{\r\n name: \"John\",\r\n id: 1234567890,\r\n salary: 60000\r\n },\r\n {\r\n name: \"Jack\",\r\n id: 0987654321,\r\n salary: 55000\r\n }\r\n ],\r\n location: {\r\n building: {\r\n address: \"111 Main St\"\r\n }\r\n }\r\n};\r\n\r\nlet properties = ['location', 'building', 'address'];\r\n\r\n// we use this to traverse the object storing the parent\r\nlet parent = null;\r\n// run over each property in the array\r\nfor (let i = 0; i < properties.length; i++) {\r\n // check if this is the last property and we have the parent object\r\n if (i + 1 == properties.length && parent)\r\n delete parent[properties[i]]; // just delete the property from the object\r\n else if (parent === null)\r\n parent = jsObject[properties[i]] // set the initial parent\r\n else\r\n parent = parent[properties[i]] // set the parent to the property in the existing object\r\n}\r\n// log the output\r\nconsole.log(jsObject);",
2018-07-20T21:40:03
Nina Scholz :

You could reduce the object by the keys and save the last key for deleting the object with that key.\n\n\r\n\r\nfunction deleteKey(object, keys) {\r\n var last = keys.pop();\r\n delete keys.reduce((o, k) => o[k], object)[last];\r\n return object;\r\n}\r\n\r\nvar object = { employees: [{ name: \"John\", id: '1234567890', salary: 60000 }, { name: \"Jack\", id: '0987654321', salary: 55000 }], location: { building: { address: \"111 Main St\" } } };\r\n\r\nconsole.log(deleteKey(object, ['location', 'building', 'address']));\r\n.as-console-wrapper { max-height: 100% !important; top: 0; }",
2018-07-20T21:52:08
yy