Question

Let's say I POST this simple JSON payload:

{"foo":null}

On the ColdFusion server, how do I check if the 'foo' property is null?

IsDefined won't work because it will be false for null values. IsNull won't work because IsNull will be true for not just null values, but also for missing properties.

<cfset json = DeserializeJSON(GetHttpRequestData().content) />
<cfdump var="#IsDefined("json.foo")#" /> <!--- false --->
<cfdump var="#IsNull(json.foo)#" /> <!--- true --->
<cfdump var="#IsNull(json.bar)#" /> <!--- true --->
Was it helpful?

Solution

My mistake, I thought null in JSON would be deserialized to empty string, but it's not true.

null in JSON is translated to be struct with key foo but undefined in CF10. (not sure about older CF version)

enter image description here

Therefore, a true isStructValueNull() can be written like this:

function isStructValueNull(struct, key) {
    return listFind(structKeyList(struct), key) 
             && !structKeyExists(struct, key);
}

json = deserializeJSON('{"foo":null,"bar":123}');

writeDump(isStructValueNull(json, "foo"));    // yes
writeDump(isStructValueNull(json, "bar"));    // no

or you can loop through json and use structKeyExists(), if it's false, it's null.

function structNullKeyList(struct) {
    var nulls = "";
    for (var key in struct) 
       if (!structKeyExists(struct, key))
         nulls = listAppend(nulls, key);
    return nulls;
}

writeDump(structNullKeyList(json));           // 'foo'

OTHER TIPS

How are you posting this data? What do you get when you dump just the variable "json"?

If you're POSTing data to ColdFusion, each parameter should get converted to a FORM scoped variable. Check the headers of your HTTP POST to see how the data is being sent.

If they're being sent as individual parameters, you should be able to get check <cfif structKeyExists(form, "foo")> and then check to see if the value of form.foo is an empty string. (ColdFusion translates a NULL value to an empty string.)

I use Raillo.

Railo 4.1.3.005 Error (expression) Message the value from key [FOO] is NULL, which is the same as not existing in CFML.

But we can use Full Null suport. Where it can be properly examined, as you want.

<cfscript>

    objectValues = { 'one' : 1 , 'two' : 2 , 'three' : JavaCast( "null", 0 ) , 'four' : null };

    dump(objectValues);

    // Known existing attribute
    dump('three');
    dump( isDefined('objectValues.three') );
    dump( isNull(objectValues.three) );
    dump( StructKeyExists(objectValues,'three') );

    // Known Railo Null value
    dump('four');
    dump( isDefined('objectValues.four') );
    dump( isNull(objectValues.four) );
    dump( StructKeyExists(objectValues,'four') );

    // Unknown existing attribute
    dump('five');
    dump( isDefined('objectValues.five') );
    dump( isNull(objectValues.five) );
    dump( StructKeyExists(objectValues,'five') );

</cfscript>

What's your ColdFusion Version?

Actually a true JSON null value should be translated to 'null' by Coldfusion which is equally annoying but manageable

If you store just an empty string in the struct like this:

<cfset s = StructNew()>
<cfset s.test = "" />
<cfset json = SerializeJSON(s)>
<cfdump var="#json#">
<cfset d = DeserializeJSON(json)>
<cfdump var="#d#">

You get the following json: {"TEST":""} and d.test is ""

But if you explicitly store a java null in the struct like this:

<cfset s = StructNew()>
<cfset s.test = javaCast( "null", "" ) />
<cfset json = serializeJSON(s)>
<cfdump var="#json#">
<cfset d = DeserializeJSON(json)>
<cfdump var="#d#">

you get the following json value: {"TEST":null} and d.test is 'null'

This is probably more preferable as you could do this:

<cfif StructKeyExists(d,"TEST") AND Compare(d.test,"null") IS 0>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top