Welcome to null in ColdFusion. Let me explain why a key does and does not exist.
NULL in Query
First of all, let's see why many developers new to CFML are confused. One of the first things you learn is:
<cfquery>
SELECT NULL AS cellWithNull;
</cfquery>
will turn out as

Reason
ColdFusion has no native support for NULL and will treat this value as an empty string.
null in Java
At some point, you might need to pass a real null value to a Java method.
// Java
x = new org.example.FooBar();
x.someMethod(null);
Yet if you try to use or define a variable with null in CFML, such as:
y = null;
ColdFusion will throw an exception: Variable NULL is undefined.
Reason
ColdFusion has no native support for null. In fact, it does not even recognize null and will attempt to resolve it as a variable by name instead.
// this will work
null = "";
y = null;
// y = [empty string]
Solution
// ColdFusion
x = createObject("java", "org.example.FooBar").init();
x.someMethod(javaCast("null", ""));
javaCast("null", "") exists for this use case. (The second argument has no meaning btw.)
null in JSON (object)
x = deserializeJSON('{ "key": null }');
will turn out as

Reason
ColdFusion has no native support for ... wait, what? Exactly, when deserializing null, the value will be treated as undefined, making the key to the value exist and not exist at the same time.
structKeyList(x)
>> "key"
structKeyArray(x)
>> [ "key" ]
structKeyExists(x, "key")
>> false
isNull(x.key)
>> true
isNull(x["key"])
>> true
x.key
>> Exception: Element KEY is undefined in X.
writeDump(x["key"])
>> undefined
writeOutput(x["key"])
>> [empty string]
Solution
When iterating over keys of a struct, always check if the value behind the key is "defined" according to ColdFusion's standard. Use either structKeyExists or isNull to check the value.
null in JSON (array)
x = deserializeJSON('[ null ]');
will turn out as

Reason
You know the drill by now.
arrayLen(x)
>> 1
isNull(x[1])
>> Exception: Element 1 is undefined in a Java object of type class coldfusion.runtime.Array.
writeDump(x[1])
>> Exception: Element 1 is undefined in a Java object of type class coldfusion.runtime.Array.
writeOutput(x[1])
>> Exception: Element 1 is undefined in a Java object of type class coldfusion.runtime.Array.
arrayIsDefined(x, 1)
>> false
Solution
Always check with arrayIsDefined before accessing an array index, if you expect the array to contain null values.
ColdFusion functions without return value (void)
Not returning any value in a function, yet assigning the return to a variable will also turn out undefined.
function foo() { return; }
x = foo();
writeDump(x);
>> Exception: Variable X is undefined.
yet
x = { key: foo() };
writeDump(x);

#JustColdFusionThings
It's worth noting that newer versions of ColdFusion (and Lucee in general) support native null values. It still feels clunky working with them.