ColdFusion doesn't preserve the order in which elements were assigned to the structure.
This gives a problem when, in my particular case, I need to create a SOAP envelope from this structure and the receiver needs to data in the envelope in a particular order.
Starting from ColdFusion 2016 and higher, there is a "type" option in the StructNew() method where you can specify "Ordered". Unfortunately, I'm still on CF9.02...
For example (in CF9):
<cfscript>
myStruct=StructNew();
myStruct.one=StructNew();
myStruct.one.item1="Old Trafford";
myStruct.one.item2="Anfield";
myStruct.two=StructNew();
myStruct.two.item3="Stamford Bridge";
myStruct.two.item4="Villa Park";
myStruct.three=StructNew();
myStruct.three.item5="St James Park";
myStruct.three.item6="Emirates Stadium";
WriteDump(myStruct);
</cfscript>
Output:
{"ONE":{"ITEM2":"Anfield","ITEM1":"Old Trafford"},"THREE":{"ITEM6":"Emirates Stadium","ITEM5":"St James Park"},"TWO":{"ITEM4":"Villa Park","ITEM3":"Stamford Bridge"}}
As you can see, the order is scrambled.
A second problem is the UPPERCASE. All the items are transformed to uppercase...
This is a problem for a SOAP envelope, because it is case sensitive.
Order.
The solution is to use a java LinkedHashMap which can be used just like a structure in ColdFusion.
So, I just need to replace
StructNew();
with: createObject("java", "java.util.LinkedHashMap").init();
Uppercase:
Assign/address them though their string name. This will preserve the case.
So, the example becomes:
<cfscript>
myStruct=createObject("java", "java.util.LinkedHashMap").init();
myStruct['one']=createObject("java", "java.util.LinkedHashMap").init();
myStruct['one']['item1']="Old Trafford";
myStruct['one']['item2']="Anfield";
myStruct['two']=createObject("java", "java.util.LinkedHashMap").init();
myStruct['two']['item3']="Stamford Bridge";
myStruct['two']['item4']="Villa Park";
myStruct['three']=createObject("java", "java.util.LinkedHashMap").init();
myStruct['three']['item5']="St James Park";
myStruct['three']['item6']="Emirates Stadium";
WriteDump(SerializeJSON(myStruct));
</cfscript>
Output:
{"one":{"item1":"Old Trafford","item2":"Anfield"},"two":{"item3":"Stamford Bridge","item4":"Villa Park"},"three":{"item5":"St James Park","item6":"Emirates Stadium"}}
Nicely ordered and case preserved!
This is exactly how we retained key order using ColdFusion 8. Please note that if you serialize the data using JSON or WDDX, it will retain the order, but deserializing will ignore it. (If key order is important when deserializing, consider adding an array prior to serialization that contains the specific order of the keys.)
Thanks for the heads-up concerning deserialization! This was just used for the example here, I'm transforming the struct to a XML (kind off, SOAP envelope) in my application.