Casting Java Structs And Arrays To ColdFusion Structs And Arrays
Most of the time, in modern ColdFusion, data flows seamlessly in between the ColdFusion layer and the underlying Java layer. Behind the scenes, ColdFusion is working to cast or proxy objects, as needed, so that we can consume these objects as if they were native ColdFusion data types. But, this magic isn't always perfect. In some edge-cases, we have to explicitly cast Java objects into ColdFusion objects in order to consume the full object API (such as member methods).
As an example from yesterday, I had to cast a Java array into a ColdFusion array when polyfilling the name[]
form field functionality in Adobe ColdFusion. And, a few years ago, I should have used this approach when trying to consume a MongoDB BSON Document as a ColdFusion struct.
I don't think there's a one-size-fits-all solution here. But, the few times that I've come up against this edge-case, the following technique always seems to work: I create a native ColdFusion object and then "append" the Java object to it. This creates a shallow copy of the Java object, swapping out the outer "Java shell" for a "ColdFusion shell".
<cfscript>
javaArray = javaCast( "string[]", [ "hello", "world" ] );
dump( javaArray );
dump( toCFArray( javaArray ) );
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
javaObject = createObject( "java", "java.util.Hashtable" ).init();
javaObject.put( "foo", "bar" );
javaObject.put( "answer", 42 );
dump( javaObject );
dump( toCFStruct( javaObject ) );
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
/**
* I cast the given Java Array to a ColdFusion array using a shallow copy.
*/
public array function toCFArray( required any javaValue ) {
return( arrayNew( 1 ).append( javaValue, true ) );
}
/**
* I cast the given Java Object to a ColdFusion struct using a shallow copy.
*/
public struct function toCFStruct( required any javaValue ) {
return( structNew().append( javaValue ) );
}
</cfscript>
This technique works because the given Java objects are usually "Array-like" or "Struct-like"; and, ColdFusion knows how to iterate over said object values. And, if ColdFusion can iterate over the values, ColdFusion can append those values to a native ColdFusion data type.
If we run this Lucee CFML code, we get the following output:
As you can see, the native Java array and hash-table types (represented in orange) have been cast to a native ColdFusion array and struct, respectively.
Aside: In reality, Java
Hashtable
classes can be treated like native ColdFusion structs - it is one of the classes that ColdFusion handles seamlessly. But, I needed something to demo.
Again, this isn't meant to be a universally applicable solution. But, for simple data types, this technique has served me well.
Want to use code from this post? Check out the license.
Reader Comments
TIL how to create java arrays and structs and how they're different from CF arrays and structs. Thanks!
@Chris,
So, a lot of the time you don't even have to know the difference. Usually, it only matters when:
If you don't need to do that kind of stuff, ColdFusion will almost always shield you from having to know how the data is represented. 99% of the time, it just works 🤩
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →