1

I'm trying to put content from RSS feed - problem is every RSS feed has different formats for images, content etc.

I'm trying to see if certain object exists in javascript or jquery:

item.mediaGroups[0].contents[0].url

How can I check it in an if statement? I keep getting for feeds without this structure:

Uncaught TypeError: Cannot read property '0' of undefined 

Also tried:

if (typeof item.mediaGroups[0].contents[0].url === "undefined")

but I keep getting the same error.

thanks!

0

6 Answers 6

6

There is no "simple" built in way to do this sort of in depth checking. The reasoning is simple - most of the time you know the type of the objects you're working against.

You can do:

if (typeof item !== "undefined" &&
    typeof item.mediaGroups !== "undefined" &&
    typeof item.mediaGroups[0] !== "undefined" &&
    typeof item.megiaGroups[0].contents !== "undefined" &&
    typeof item.megiaGroups[0].contents[0] !== "undefined" &&
    typeof item.mediaGroups[0].contents[0].url !== "undefined"){

When you type all that you might want to consider your data structures, since this really is not a situation you should be in to begin with :)

(hint, you can skip the typeof on all but the first, but I think typeof is a good clarification here).

The real question is this:

Why are you not sure what the structure of your data is?

If you are querying data (for example XML in an RSS feed) there are effective ways to do so with XPATH or query selectors. Object property access is built for objects where what you're querying is a document. Sure, it's possible with a bunch of ugly checks just like you can hammer a nail in with a heavy screwdriver.

You can see this question in Stack Overflow on how to use DOM methods to parse XML.

Sign up to request clarification or add additional context in comments.

4 Comments

thanks. I don't know what the structure because RSS of various sites is different in terms of their structure. so I have to build a special 'filter' for each (which is a little stupid I know as RSS should have 'normelized' it...)
@mojoo It's not 'stupid' at all, it's a very common problem which has been already dealt with by a lot of people. You're not the first of 1000th guy to need to read unfamiliar HTML/XML structure. This is what the DOM API is built for. You have a perfectly good hammer to use for your nails, use it :)
Don't forget the "s" at those three mediaGroup words in the middle. Personally, I would just leave out the typeofs, because they don't cover null.
@RobW Names noted and fixed. I hope it's clear that that example is only there to show how absurd that approach is. What OP is trying to do (querying RSS) can be done with a short query selector or XPATH query, it'll be faster, more concise and clearer too :)
1

If you're uncertain about the exisence of properties, try this helper function:

function getProperty(root) {
    var l = arguments.length, i, undefined;
    for( i=1; i<l; i++) {
        if( typeof root[arguments[i]] == "undefined") return undefined;
        root = root[arguments[i]];
    }
    return root;
}

You can then call it like this:

var url = getProperty(item,'mediaGroups',0,'contents',0,'url');

As a more "haxy" way, you can try this:

try {url = item.mediaGroups[0].contents[0].url;}
catch(e) {url = undefined;}

4 Comments

can I pass to the function this: item.mediaGroups[0].contents[0].url? I'm assuming that what I will need to check will change as I make the tweeks from feed to feed so I would like something that will work regardless
No, because then you're trying to access the end of the chain without checking it, which is what it causing the error in the first place.
why are you declaring undefined as a variable?
@Stuart To ensure it's undefined. Older browsers allow you to overwrite the variable, this guarantees it to be undefined.
1

I would check the length of both arrays in this case to be sure - before assuming there are objects defined at index 0

item.mediaGroups.length > 0

and

item.mediaGroups[0].contents.length > 0

As the outer check you can also throw in a

if(item.mediaGroups){
} 

1 Comment

I was trying to avoid all the extra checks, Wanted a simple check for the object which I understand is not possible
0

How about 'optional chaining' (described in ES2021 spec and already implemented in all browsers except three) ?

from MDN:

The optional chaining operator provides a way to simplify accessing values through connected objects when it's possible that a reference or function may be undefined or null.

The optional chaining ?. stops the evaluation if the value before ?. is undefined or null and returns undefined so it is giving us a way to handle the possibly undefined/nullsish values

item?.mediaGroups[0]?.contents[0]?.url // will evaluates to undefined if either of those is undefined.

Comments

-1

item.mediaGroups[0].contents is undefined, you have to check for it.

if(item.mediaGroups && item.mediaGroups[0].contents) {
    return item.mediaGroups[0].contents[0].url;
}

3 Comments

Someone is having fun down voting all the answers, shouldn't there be a way to report that?
you are missing many checks. What if item.mediaGroups[0] is undefined?
I was trying to avoid testing each part of the object... a little like isset in php
-1

It's not a solution with if-statements (as requested), but you can use exceptions to achieve similar functionality. Something like this:

function throwOrReturn(thing){

    if(typeof thing === 'undefined'){

        throw "Didn't find it..."

    }else{

        return thing

    }

}

// The unknown thing.
var a = {
    b1: {
    },
    b2: {
        c: 'lookingFor'
    }
}

var c

// Test our different paths.
try{

    // First guess.
    c = throwOrReturn(a.b1.c.d)+" - a.b1.c.d"

}catch(error){

    try{

        // Second guess.
        c = throwOrReturn(a.b[45][34].c)+" - a.b[45][34].c"

    }catch(error){

        try{

            // Third guess.
            c = throwOrReturn(a.b2.c)+" - a.b2.c"

        }catch(error){

            // Try more guesses, or give up.
            c = "notFound"

        }

    }

}

console.log("c:", c) // Logs: "c: lookingFor - a.b2.c" 

It ain't pretty, but it's an alternative worth to mention.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.