简体   繁体   中英

How to avoid “null” values in a Json Object , when looping over it

I am learning vainilla JS (sorry in advance if I don't use some concepts properly), and while doing so, I am practising DOM manipulation and API fetching, with a free API i was given.

I have JSON with an structure similar to the one below, in which sometimes some fields get the value null ,or even change the structure of the attribute (as you can see in the 'Image Gallery' from the 3rd elelement.

I am looping through it to do different things, like creating a table, buidling some cards, and create an img gallery displaying the images from that element when clicking a button. But whenever the loop finds the "null" value, it stops, and gives me a Cannot read property 'length' of null

The object is similar to this :

myObject = [
    {
        "field one": "something ",
        "Image Gallery": [
            {
                "src": "anImage.jpg",
                "title": "more text"
            },
            {
                "src": null,
                "title": "a title here"
            },
            {
                "src": "otherImg.jpg",
                "title": null
            }      
        ],
        "Management": null,
        "Scientific Name": "Urophycis tenuis",
        "Species Illustration Photo": {
            "src": null,
        },
        "last_update": "05/19/2021 - 13:04"
     },
    {
        "Habitat Impacts": "something ",
        "Image Gallery": null,
        "Management": 'some value',
        "Scientific Name": null,
        "Species Illustration Photo": {
            "src": 'img.jpg',
        },
        "last_update": "05/19/2021 - 13:04"
     },
    {
        "Habitat Impacts": "something ",
        "Image Gallery":  // Note that the Image gallery structure is an array here
            {
                "src": "anImage.jpg",
                "alt": "some text",
                "title": "more text"
            },     
        ,
         "Management": 'some value',
        "Scientific Name": "Urophycis tenuis",
        "Species Illustration Photo": {
            "src": 'img.jpg',
        },
        "last_update": "05/19/2021 - 13:04"
    }]

My Javascript code in which I get the error is :

function createCards(myObject) {
    let cardContainer = document.getElementById('cardContainer');
    
    for (let i = 0; i < myObject.length; i++) {
            
        aInfoButtonLeft.onclick = function () {
            
            for (let x = 0; x < myObject[i]["Image Gallery"].length; x++) {   
                console.log(myObject[i]['Image Gallery'][x]["src"])
            }
        }
    }

}

How could I prevent the different "null" values to break the iteration, or to skip them and follow with the next value? The only way I can think of is to write if conditions, but I would need one per every kind of attribute which might contain a Null

  • Try with an if statement. It will catch null and undefined objects:

     if (myObject[i]["Image Gallery"] != null) { for (let x = 0; x < myObject[i]["Image Gallery"].length; x++) { console.log(myObject[i]['Image Gallery'][x]["src"]) } }

While most languages with loops have the break statement, a good set of them also have the continue statement, including JavaScript. This allows you to easily "skip" the current iteration:

for (let i = 1; i <= 4; i++) {
    console.log('A' + i);
    if (i%2 == 0) continue; // Only if a multiple of 2
    console.log('  B' + i);
}

> A1
>   B1
> A2
// no B2
> A3
>   B3
> A4
// no B4

For your first problem, being dealing with null values, you can simply check and continue. For your second problem, where the "Image Gallery" has a different structure at times, there are a few options:

  1. Handle a single object and an array of objects differently
  2. Convert a single object to an array of objects (with just that one object)

also I'm assuming that your code comment "Note that the Image gallery structure is a string here" meant to say that it's an array.

Showcasing both solutions at once, along with solving your first problem, we get something like this:

function createCards(myObject) {
    let cardContainer = document.getElementById('cardContainer');

    for (let i = 0; i < myObject.length; i++) {

        let imgGallery = myObject[i]["Image Gallery"];

        // For the first problem, ignore null values
        if (imgGallery == null) continue;

        /* - - - Example of 1st solution to 2nd problem (begin) - - - */
        // Check whether imgGallery is an array (presumably of image objects)
        if (Array.isArray(imgGallery)) {
            // imgGallery is an array of images, iterate over it
            for (const img of imgGallery) {
                // handle img as an image
            }
        } else {
            // imgGallery is already an image object
            // handle imgGallery as an image
        }
        // The function would end here
        /* - - - Example of 1st solution to 2nd problem (end) - - - - */

        // 2nd solution for 2nd problem, we could force it to be an array
        if (!Array.isArray(imgGallery))
            imgGallery = [imgGallery];
        // so we can just use the original code, except we now use
        // the imgGallery variable of which we know it's an array
        aInfoButtonLeft.onclick = function () {
            for (let x = 0; x < imgGallery.length; x++) {
                // I noticed the .src can still be null, which we want to skip?
                // Mind that `continue`, just like `break`, works on the "closest" loop
                if (imgGallery[x].src == null) continue;
                console.log(imgGallery[x].src)
            }
        }
    }
    
}

I noticed that image objects themselves can still have a src that's null . Adding another simple (if src == null) continue; check is all you need, as shown in the updated code above.

You can always check if the value is not null like below

if(value){
    //exists
}else{ console.log("value is null"); }

As posters above have mentioned, you'd need to check whether the value is null. You simply can't loop through an object that doesn't exist! So your choice would be not to use null objects in your structure -I'm not quite sure why you need them in the first place, maybe you could have a structure you loop through and another, placeholder structure - OR to check for null.

Onclick function should be outside of both of for loops.

ps: Using the snippet makes things easier.

 var myObject = [{ "field one": "something ", "Image Gallery": [{ "src": "anImage.jpg", "title": "more text" }, { "src": null, "title": "a title here" }, { "src": "otherImg.jpg", "title": null } ], "Management": null, "Scientific Name": "Urophycis tenuis", "Species Illustration Photo": { "src": null, }, "last_update": "05/19/2021 - 13:04" }, { "Habitat Impacts": "something ", "Image Gallery": null, "Management": 'some value', "Scientific Name": null, "Species Illustration Photo": { "src": 'img.jpg', }, "last_update": "05/19/2021 - 13:04" }, { "Habitat Impacts": "something ", "Image Gallery": // Note that the Image gallery structure is a string here { "src": "anImage.jpg", "alt": "some text", "title": "more text" }, "Management": 'some value', "Scientific Name": "Urophycis tenuis", "Species Illustration Photo": { "src": 'img.jpg', }, "last_update": "05/19/2021 - 13:04" } ] function createCards(myObject) { let cardContainer = document.getElementById('cardContainer'); aInfoButtonLeft.onclick = function() { for (let i = 0; i < myObject.length; i++) { if (myObject[i]["Image Gallery"]) { for (let x = 0; x < myObject[i]["Image Gallery"].length; x++) { console.log(myObject[i]['Image Gallery'][x]["src"]) } } } } } createCards(myObject)
 <input id="aInfoButtonLeft" type="button" value="Button">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM