Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Alec Irwin
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Alec Irwin

ColdFusion 9's IsNull() Works On Non-Struct Objects

By Ben Nadel on
Tags: ColdFusion

When I first did my exploration of ColdFusion 9's isNull() function, I definitely came away thinking that the isNull() function was merely a short-hand, convenience notation for the existing structKeyExists() function. The other day, however, when blogging about creating proxy objects, I was dealing with a situation in which the base value that I was checking might not always be an object with a struct-like interface. In a scenario like that, my first instinct was to check for "struct-ness" before I checked for "null-ness:"

  • <cfif (
  • isStruct( someValue ) &&
  • !isNull( someValue.someKey )
  • )>
  • <!--- Do some conditional logic here... --->
  • </cfif>

As you can see here, I'm using the short-circuiting nature of ColdFusion's conditional statements in order to check that the value was both a struct and that a key off of that struct was non-null. On a whim, I decided to see if I could remove the isStruct() condition. And, much to my delight, it turns out that isNull() works on simple values just as well as it works on structs.

  • <!--- Create a string value. --->
  • <cfset myString = "Boo ya!" />
  • <!--- Check for a property of it. --->
  • String Key Null: #isNull( myString.someKey )#

As you can see, we are checking for a property of a string value (which is typically a no-no in ColdFusion). When we run the above code, we get the following output:

String Key Null: YES

It correctly determines that the given key path cannot be gotten off of the given base value. It doesn't matter at all that the base value is a simple value and not a struct (or struct-like object).

Now, like I said, it was sort of my assumption that isNull() was a short-hand for structKeyExists(); however, if we try to rewrite the previous statement using structKeyExists():

  • <!--- Create a string value. --->
  • <cfset myString = "Boo ya!" />
  • <!--- Check for a property of it. --->
  • String Key Exists: #structKeyExists( myString, "someKey" )#

... we get the following ColdFusion error:

You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members.

As you can see, when we explicitly treat the string as a struct, we get an error; but, if we let isNull() do the key-path checking, the data type doesn't matter.

I know this is a really minor point, but if you think that isNull() is nothing more than a short-hand for structKeyExists() - just as I sort of did - then you really aren't leveraging isNull() to its full potential. ColdFusion 9's isNull() function allows you essentially confirm both data type and key path existence within a single conditional statement.

Reader Comments

For what it's worth, I use IsDefined("struct1.struct2.struct3.key") all the time without first checking struct1, struct2 or struct3. I can't recall ever using StructKeyExists. But then, that's just me. StructKeyExists probably compiles to much more efficient Java.


To be honest, I don't use isDefined() enough to know the rules behind it. That's cool that you can use arbitrary data types as well. I know there are some differences between isNull() and isDefined(), specifically when checking for scope existence:

It seems that isNull() isn't quite like structKeyExists() and it isn't quite like isDefined(). It's some magical beast unto itself :)

You know how Evaluate() translates a string (with possible #-sign substitutions if it's a string literal) into a variable reference, right? Well basically, for any string, if IsDefined(string) is true, Evaluate(string) will not crash.

In the IsDefined("struct1.struct2.struct3.key") example, I don't really care why it failed: struct1 may not exist, or struct1 may not be a struct, or struct1.struct2 might not exist, etc, etc. All of those possibilities result in the IsDefined() call returning false.

I think you've hit on something with IsNull(). It's sort of similar to a Java HashMap or TreeMap. If you try to get() a key you never put(), the get() returns false. It's like IsDefined("ref") with quotes is equivalent to IsNull(ref) without quotes.