Home Check if a nested chain of objects is valid
Post
Cancel

Check if a nested chain of objects is valid

A core variable type in BrightScript is the associative array. These arrays allow objects to be accessed using keys. The access methods I’ve seen used most often are dots or brackets.

Here’s an example using dots to access a deeply nested associative array.

1
2
3
4
5
6
7
8
9
movie = { 
    data: {
        overview: {
            slug: "Just When You Thought It Was Safe To Go Back In The Water"
        }
    }
}

print movie.data.overview.slug

And here’s an example using brackets.

1
2
3
4
5
6
7
8
9
movie = { 
    data: {
        overview: {
            slug: "Just When You Thought It Was Safe To Go Back In The Water"
        }
    }
}

print movie.data.overview["slug"]

Often times you’ll see the bracket method used when the key’s value comes from a variable.

1
2
3
4
5
6
7
8
9
10
movie = { 
    data: {
        overview: {
            slug: "Just When You Thought It Was Safe To Go Back In The Water"
        }
    }
}

keyToLookup = "slug"
print movie.data.overview[keyToLookup]

These methods will work as long as your data is 100% as expected and offers no surprises.

Which we programmers know is how data always is…

😂😆🤣 Just kidding, data is always a mess and should never be trusted!

Let’s look back at our dot example above.

What happens if our data doesn’t have an overview object?

Exception has occurred. Dot Operator attempted with invalid BrightScript Component or interface reference.

Yikes! The last thing we want is our channel to crash because our data is in an unexpected format.

That means we should check every key in the object chain - all the way down to the data we need.

One way to do this is nested if statements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
movie = { 
    data: {
        overview: {
            slug: "Just When You Thought It Was Safe To Go Back In The Water"
        }
    }
}

if isValid(movie)
    if isValid(movie.data)
        if isValid(movie.data.overview)
            if isValid(movie.data.overview.slug)
                print movie.data.overview.slug
            end if
        end if
    end if
end if

Isn’t that so pretty that you want it all over your code! 🤢

Now, you may be asking “Why not simply use BrightScript’s built in optional chaining support?”

Again, in a perfect world where we can trust the data, that would work, but we don’t want to use it because optional chaining only checks if the item in the chain is valid, it does not also check if the item is an associative array. This can lead to exceptions being throw.

In the example above, what if in the returned data overview was a string? It could lead to several types of errors depending on your code.

Technically the overview object is valid, but it’s not an associative array, it’s a string. So the client throws a syntax error because we’re attempting to access a property value as if it were.

Exception has occurred. Syntax Error.

That’s why I created a helper function that will step through the object chain checking if each key is valid and will return false as soon as it hits an invalid item.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function isChainValid(root as dynamic, propertyPath as string) as boolean
    rootPath = root
    properties = propertyPath.Split(".")

    if not isValid(rootPath) then return false

    ' Root path is valid, and no properties were passed. Return state of root
    if properties.count() = 0 then return true
    if properties[0] = "" then return true

    rootPath = rootPath.LookupCI(properties[0])

    if not isValid(rootPath) then return false

    properties.shift()

    if properties.count() <> 0
        nextPath = properties.join(".")
        return isChainValid(rootPath, nextPath)
    end if

    return true
end function

Using the isChainValid function, we can condense the entire object chain validation check into a single if statement. Simply pass in a root object and a string of keys separated by periods and isChainValid will safely check if each key is valid before checking the next one in the chain.

1
2
3
4
5
6
7
8
9
10
11
movie = { 
    data: {
        overview: {
            slug: "Just When You Thought It Was Safe To Go Back In The Water"
        }
    }
}

if isChainValid(movie, "data.overview.slug")
    print movie.data.overview.slug
end if
This post is licensed under CC BY 4.0 by the author.

Trending Tags