ColdFusion: Get variable type

Variables in CF are type-less. It's up to developer best-practices to use them properly but CF treats variables the same whether they are integers or strings.

For structs or arrays or components/functions more details are available through CFDUMP.


Here is a slightly updated version. This includes additional ColdFusion struct datatypes

<cfscript>
 TypeTest = {array   = []
    , struct  = {}
    , orderedstruct = [:]
    , sortedstructNumeric = StructNew("ordered","numeric")
    , sortedstructText = StructNew("ordered","text")
    , string  = "123"
    , number  = 123
    , boolean = true
    , date    = Now()
    , number2 = 1+1
    };


TypeTest.each(function(key, value) {
    TypeTest[key] = {"value" : value,  "meta" : getMetadata(value).getName() };
    });

writedump(TypeTest);
</cfscript>

Results

enter image description here


CFML is dynamically typed, so types can change as required.

You can see the current (JVM) type of a variable by doing <cfdump var=#getMetadata(var)# /> or simply by accessing getMetadata(var).getName().

Generally, you don't care whether something is a specific type, so much as whether it can be automatically cast to a specific type - for this reason there are functions including isSimpleValue, isNumeric, isDate, and various others.

So if calling isNumeric(string) returns true, then you know that you can use that variable for mathematical purposes.

For the most part, that's all the average CF developer cares about, and the rest of this answer probably isn't important (but of course might still be interesting).

ColdFusion and Types

If you have reason to deal with types directly, you need be aware that Adobe ColdFusion does funny things with types - doing <cfset number = 123 /> results in a string not a numeric type.

Indeed, most simple values in ACF are created as strings, (and then automatically cast to the relevant type when needed).

At the same time, not all simple values are stored as strings - if you do <cfset number = 1 + 1 /> then you get a number instead.

You can see the types used with this code:

<cfset TypeTest =
    { array   = []
    , struct  = {}
    , string  = "123"
    , number  = 123
    , boolean = true
    , date    = Now()
    , number2 = 1+1
    }/>

<cfloop item="key" collection=#TypeTest# >
    <cfoutput><br/> #key# = #getMetadata(typetest[key]).getName()#</cfoutput>
</cfloop>


The results of this code in CF10 are like so:

ARRAY = coldfusion.runtime.Array
STRUCT = coldfusion.runtime.Struct
STRING = java.lang.String
NUMBER = java.lang.String
BOOLEAN = java.lang.String
DATE = coldfusion.runtime.OleDateTime
NUMBER2 = java.lang.Double

The reason for this long-winded explanation is that if CF was to show type when you dumped, half the time it would say "string" and not necessarily be very useful.

Workaround

If you need to know [potential] types then you would need to create your own dump tag/function which makes use of conversion checking functions described above to determine what you are looking at and output the relevant information.

Railo and Types

As mentioned in the comment by Busches, Railo (an alternative CFML engine) does show types when you dump, and it shows correct types.

This is because Railo doesn't just convert (almost) everything to a string - it starts with the relevant type, and converts if needed.

To show this, you can run the above code snippet, here are the results of running against Railo 3.3:

ARRAY = railo.runtime.type.ArrayImpl
STRUCT = railo.runtime.type.StructImpl
STRING = java.lang.String
NUMBER = java.lang.Double
BOOLEAN = java.lang.Boolean
DATE = railo.runtime.type.dt.DateTimeImpl
NUMBER2 = java.lang.Double

If you wanted a simple one-word type, you can probably get a sensible value with this:

ListLast(type,'.').replaceAll('Impl$','')

(There is no specific Java->CFML conversion function - you can see how the type labelling is done for cfdump by looking at the relevant source code.)