So I have an object inside a json file like this:
{
"0": {
"damage_type": "Scratch",
"regions": []
},
"1": {
"damage_type": "Dent",
"regions": []
},
"2": {
"damage_type": "Dent",
"regions": [
"front side",
"front window"
]
}
}
What I am trying to accomplish is to remove the object that have empty regions. Like this:
{
"2": {
"damage_type": "Dent",
"regions": [
"front side",
"front window"
]
}
}
I am using a for loop and still unsuccessful:
jsonfile.readFile(theJsonFile, function (err, obj) {
if (err) console.error(err)
for (var i = 0; i <= Object.keys(obj).length - 1; i++) {
if (obj[i].damage_type.length < 1) {
delete obj[i]
}
}
}
Any ideas?
5 Answers 5
Calling the parsed value damages instead of obj, you can grab all entries as key/value pairs, iterate over them and remove no-region "damages" by their ids:
Object.entries(damages).forEach(([id, damage]) => {
if (!damage.regions.length) {
delete damages[id];
}
});
Alternatively, you can create a brand new structure without touching the original structure:
const entries = Object.entries(damages);
const filteredEntries = entries.filter(([_, damage]) => damage.regions.length);
const filteredDamages = Object.fromEntries(filteredEntries);
Comments
In this case first you need an array. To convert object to arrays use entry entry
let obj = {
"0": {
"damage_type": "Scratch",
"regions": []
},
"1": {
"damage_type": "Dent",
"regions": []
},
"2": {
"damage_type": "Dent",
"regions": [
"front side",
"front window"
]
}
}
converting array :
const myentry= Object.entries(obj);
Now the best way to eliminate or filter array is to use filter method and in return get the other object which have filter value.
const myFiletrObj = myentry.filter(([_, obj]) => obj.regions.length).reduce(withObjectAssign, {})
function withObjectAssign(object, [key, value]) {
return Object.assign(object, {[key]: value})
}
This will give you filtered output.
Comments
made changes, try this
let json = {
"0": {
"damage_type": "Scratch",
"regions": []
},
"1": {
"damage_type": "Dent",
"regions": []
},
"2": {
"damage_type": "Dent",
"regions": [
"front side",
"front window"
]
}
};
function walk(obj) {
for (var key in obj) {
let length = Object.keys(obj[key].regions).length; // get the length
if(length==0){
delete obj[key];
}
}
console.log(json);
}
walk(json);
output
{ '2':
{ damage_type: 'Dent',
regions: [ 'front side', 'front window' ]
}
}
1 Comment
You can delete a json node by its key
var json = { ... };
var key = "foo";
delete json[key]; // Removes json.foo from the dictionary.
1 Comment
json unless it actually contains a JSON-stringified value. In your case, you're better off calling it data, obj, value, etc.)Why your code is not working?
You are incorrectly checking the condition for damage_type.length from each node. You need to delete the nodes with empty regions. So you have to check for regions.length.
Your working Solution
const obj = {
"0": { "damage_type": "Scratch", "regions": [] },
"1": { "damage_type": "Dent", "regions": [] },
"2": { "damage_type": "Dent", "regions": [ "front side", "front window" ] }
};
for (var i = 0; i < Object.keys(obj).length; i++) {
if (!obj[i].regions || obj[i].regions.length === 0) {
delete obj[i]
}
}
console.log(obj);
This solution works only because that the key of objects are same as the index "0", "1" and "2". If the key is something else, this wont work.
Corrected solution
Get the keys using Object.keys and delete the correct node.
Working Fiddle
const obj = {
"0": { "damage_type": "Scratch", "regions": [] },
"1": { "damage_type": "Dent", "regions": [] },
"2": { "damage_type": "Dent", "regions": [ "front side", "front window" ] }
};
const keys = Object.keys(obj);
for (var i = 0; i <= keys.length - 1; i++) {
if (!obj[keys[i]].regions || obj[keys[i]].regions.length === 0) {
delete obj[keys[i]]
}
}
console.log(obj);
Generic Solution
Get the key value combination using Object.entries
const obj = {
"0": { "damage_type": "Scratch", "regions": [] },
"1": { "damage_type": "Dent", "regions": [] },
"2": { "damage_type": "Dent", "regions": [ "front side", "front window" ] }
};
const entries = Object.entries(obj);
entries.forEach(([key, value]) => {
if (!value.regions || value.regions.length === 0) {
delete obj[key]
}
})
console.log(obj);
4 Comments
Object.entries(data) to use the actual keys. With your example, it's just luck that the values will be indexed the same way as the original object's keys.Object.entries(data) or Object.keys will do the trick irrespective of the values for key.data[key] twice is still sub-par to using Object.entries() to get both the key and value at the same time. Also, the OP doesn't seem to have a need to check if the regions property exists.Object.entries(). OP needs to delete nodes with empty region. So the regions key needs to be validated for the delete condition
damage_type, notregions.