Prevent ColdFusion from converting string to number using SerializeJSON Prevent ColdFusion from converting string to number using SerializeJSON json json

Prevent ColdFusion from converting string to number using SerializeJSON


I know this issue is old, but as a new CF developer, I came across this same issue, and while I used the 'string Hack' above successfully, finally I found a more suitable resolution from the Cold Fusion docs for serializeJSON.

'Adobe ColdFusion (2016 release) Update 2 enables you to specify the datatype information for keys in a struct. This is known as metadata.'

<cfscript>   example = structnew();   example.firstname = "Yes";   example.lastname = "Man";   writeoutput("<b>After serialization</b>:");   // change the JSON key firstname to fname    metadata = {firstname: {type:"string",name:"fname"}};   example.setMetadata(metadata);   writeoutput(SerializeJSON(example));</cfscript>

While the example shows modifying the metadata for the string 'Yes', to stay a string, and not be converted to a boolean, it works just as well for turning numbers into strings for JSON serialization.


Here's a solution - albeit a very hacky, inelegant solution...

Your setup:

var test = {  name = "1234.100"};

Adding some obvious string to the front forces the value to become a string when it is converted to JSON. Then we get rid of this ugly string.

var thisIsSuchAHorribleHack = "(!@$!@$)";test.name = thisIsSuchAHorribleHack & test.name;var serializedTest = SerializeJSON(test);serializedTest = Replace(serializedTest, thisIsSuchAHorribleHack, "", "ALL");writeOutput(serializedTest);


If you have an array of variables that you want to be treated as strings (such as a postal tracking numbers "9449311899561067336896") you may run into an issue where ColdFusion thinks the strings look like numbers. ColdFusion may then try to convert the strings to integers, but if they are too long for an integer, an error may result. This could happen when the strings originated from an Array inside of Deserialized JSON.

You may think you could use the strings like this:

<cfset trackIdXml = "" />   <!--- Loop through all tracking numbers and build the XML ---><cfloop array="#trackingNumsArray#" index="i">              <cfset trackIdXml &= "<TrackID ID=""" />    <cfset trackIdXml &= #trackingNumsArray[i]# />    <cfset trackIdXml &= """/>" /></cfloop>

But it will result in an error such as Cannot convert the value 9.449311899561067E21 to an integer because it cannot fit inside an integer.

Instead you can use cfscript and java.lang.StringBuffer:

<cfscript>    //This variable will store the XML that is used in the API request to list each tracking number    //We must tell ColdFusion that this is a string buffer, and use .append(). Why?    //ColdFusion will try to convert the tracking number to a integer if we do not explicitly tell it    //to treat it as a string.    trackIdXml = createObject("java",  "java.lang.StringBuffer").init();    for (trackingNum in trackingNumsArray) {        trackIdXml.append('<TrackID ID="');        trackIdXml.append(#trackingNum#);        trackIdXml.append('"/>');    }</cfscript>

The trackIdXml variable was created inside of the cfscript tags, but can still be used like other Coldfusion variables, for example in a cfreturn <cfreturn #trackIdXml# />

Here is a full real-world example that requires integer-like strings to be kept as strings. This is a function that accepts an Array of USPS tracking numbers, and returns the package status response from the USPS's API:

<cfcomponent>    <cffunction name="uspsLookup" access="remote" returntype="string" returnformat="plain" output="yes">        <cfargument name="trackingNums" type="string" required="yes" />        <cfset trackingNumsArray = DeserializeJSON(trackingNums, true) />        <cfscript>            trackIdXml = createObject("java",  "java.lang.StringBuffer").init();            for (trackingNum in trackingNumsArray) {                trackIdXml.append('<TrackID ID="');                trackIdXml.append(#trackingNum#);                trackIdXml.append('"/>');            }        </cfscript>                <cfset userid = "XXXXXXXXXXXX" />                <cfhttp        method="GET"        url='http://production.shippingapis.com/ShippingAPI.dll?API=TrackV2&XML=<TrackRequest USERID="#userid#">#trackIdXml#</TrackRequest>'>        </cfhttp>                <cfif #cfhttp.Statuscode# IS "200 OK" >            <cfreturn "#cfhttp.Filecontent#">        <cfelse>            <cfreturn "error||#cfhttp.Statuscode#">        </cfif>      </cffunction></cfcomponent>