tomaytotomato
tomaytotomato

Reputation: 4028

Cleaning out bad JSON data from object?

I am retrieving building geolocation data from a service, however in some cases some of the data will have missing properties.

Good data

[{
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Wintefell",
    "Latitude": "52.900619",
    "Longitude": "-1.434602",
    "Region": "The North",
}, {
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Water Gardens",
    "Latitude": "51.818051",
    "Longitude": "-.354871",
    "Region": "Dorne"
}]

Bad data

Missing Region or Building Name

{
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Kings Landing",
    "Latitude": "23.818051",
    "Longitude": "-.154871",
}

After making my AJAX request I store the JSON response in an object called _regionAndBuildings

I want to clean out any bad data from it, so I tried the following code

console.log("Starting size of building data : " + _regionAndBuildings.length);
//clean json by setting object to undefined
for (var i = 0; i < _regionAndBuildings.length; i++) {
    if (_regionAndBuildings[i].BuildingName === undefined && _regionAndBuildings[i].Region === undefined) {
        console.log("Deleting");
        delete _regionAndBuildings[i];
    }
}
console.log("Ending size of building data after cleaning : " + _regionAndBuildings.length);

Output

Starting size : 209

Delete x 17

Ending size : 209

Why is this code not removing the bad elements in my JSON object?

Upvotes: 2

Views: 3224

Answers (5)

Salman Arshad
Salman Arshad

Reputation: 272116

You can do it the other way round, filter the array for good values:

var goodRegionAndBuildings = _regionAndBuildings.filter(function(item) {
    // assumes not-empty strings are good
    // everything else is bad
    return (
        item.ModifiedOn !== "" &&
        item.BuildingName !== "" &&
        item.Latitude !== "" &&
        item.Longitude !== "" &&
        item.Region !== ""
    );
});

Upvotes: 1

marsh
marsh

Reputation: 1441

The first reason - you use && instead of || there:

_regionAndBuildings[i].BuildingName === undefined && _regionAndBuildings[i].Region === undefined

But you said:

Bad data

Missing Region or Building Name

The second reason - when you delete elements from array by delete, you get a gap undefined:

[<elem>, undefined, <elem>]

Elem was removed, but length will be the same. You can remove undefined by filter later:

var newArray = yourArray.filter(function(item) { return item});

But best way is use slice instead of delete:

_regionAndBuildings.splice(i, 1);

Upvotes: 2

ozil
ozil

Reputation: 7117

In you given example

{
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Kings Landing",
    "Latitude": "23.818051",
    "Longitude": "-.154871",
}  

property BuildingName or Region is missing. It is more appropriate to usu hasOwnProperty instead of _regionAndBuildings[i].BuildingName === undefined

for (var i = 0; i < _regionAndBuildings.length; i++){
    if (!(_regionAndBuildings[i].hasOwnProperty('BuildingName')) && !(_regionAndBuildings[i].hasOwnProperty('Region'))) {
        console.log("Deleting");
        _regionAndBuildings.splice(i, 1);
     }
}  

DEMO

Upvotes: 1

thefourtheye
thefourtheye

Reputation: 239473

There are two problems in your code.

  1. As per the question

    Missing Region or Building Name

    You want to remove the elements of either Region or Building Name is missing. But the condition doesn't reflect that

    if (_regionAndBuildings[i].BuildingName === undefined && 
        _regionAndBuildings[i].Region === undefined)
    

    Since you have used && operator, only when both the expressions are satisfied, the code inside if condition will be executed. So, you need to change it with logical OR operator ||, like this

    if (_regionAndBuildings[i].BuildingName === undefined ||
        _regionAndBuildings[i].Region === undefined)
    
  2. When you use delete operator on an array, the element in the array will be deleted, but the index will point to nothing. It means the length of the array will not change. Read more about it in this section

    Instead, you can use Array.prototype.splice, like this

    _regionAndBuildings.splice(i, 1);
    

But, I prefer reconstructing the array without the elements you don't want, with Array.prototype.filter, like this

var filteredBuildings = _regionAndBuildings.filter(function (currentObject) {
    return currentObject.hasOwnProperty("BuildingName") &&
        currentObject.hasOwnProperty("Region");
});

Now, the function passed will be run with all the items in the array and only if the function returns true, the object will be included in the filtered result. So, if the object has both BuildingName and Region properties, only then it will be included in the result.


Note: I prefer using Object.hasOwnProperty to check if the property exists in the object, rather than comparing the value against undefined, because if the value of the property is actually undefined, then we cannot differentiate between a non-existing property and a property with value undefined.

Upvotes: 2

user4890880
user4890880

Reputation:

can you try :

if (typeof _regionAndBuildings[i].BuildingName === "undefined" 
       && typeof _regionAndBuildings[i].Region === "undefined")
            {
                console.log("Deleting");
               _regionAndBuildings.splice(i, 1);
}

Upvotes: 1

Related Questions