Serialize() vs serializeJSON() to maintain numbers and numbers

I have read that somewhere in the recent past, Coldfusion modified the serializeJSON() to output everything as strings vs where it use to keep a number as a number.

I was looking over the serialize() doc, and can see in the simple test that it does not convert numbers to strings (unless I am mistaken) and it appears to create a proper JSON structure. Is this something that can be reliably used in place of serializeJSON()?

Like I mention in my previous posts, I am in the process of migrating an old code set that ran in OpenBlueDragon (Which is based on CF8) and the serializeJSON() leave a number as a number. I only came across this issue when I send JSON to Walmart and Amazon, they complain that certain things should be numbers and they cannot convert a string to a number.

I also did see there is a metadata tag that can be set in Coldfusion as well, is that too available in Lucee? I do not see it mentioned in the docs. And besides that, that would require a hole load of recoding to use anyway, and I just want to get this working with the least bit of effort.

Stick with serializeJson().

Lucee uses has always used standard java types, so unlike older versions of CF serializeJson() has always preserved types consistently

image

As you can see, ACF 2025 now matches Lucee

1 Like

Interesting, I will have to see what is happening on the back end, because something is amiss. I (not into cfscript yet so bare with me):

<cfset st = StructNew() />
<cfset st.something = 1 />
<cfset st.something = "A word or what ever" />
blah blah blah...

<cfset payload = serializeJSON(st) />

Send Payload to Amazon...  
Amazon responds that it cannot convert a string to a number.

And when I think about my testing. I do remember that when I ran the block of code in a straight CFM, I had not problem with the above code. It was only when I put it into a CFC that things went weird. The cfarguments were typed as “numeric”, and they were stored into variables without a “” around them.

I see the issue now. Another catch moving to Lucee. cfinvokeargument is being cast to string regardless of it being passed a number or a string, passes the argument type test of numeric and then is stored as a string. So I used parseNumber to fix the issue.

And here I thought it was CF11’s JSON change to make everything strings, and it is nice to see Lucee did not follow.

And I guess because Lucee keeps the type cast, that removed the need to add in metadata.

I’m not seeing any casting going on with invoke argument?

Here is some screen shots
Here is the function

Here is the call

Here is the return

Am I mistaken on how to send a number in Lucee via a cfinvokeargument? Given I am coming from mainly working in CF8, I may be mistaken on what to expect from Lucee.

something missing from your example? Can’t quite follow

Sorry, I realized it had some sensitive information in it, and I was editing it out.

Here is the return
returned

I can’t repo

if you checkout testbox and lucee6

and add these mappings (testbox and test)

can you adapt the test case to demonstrate?

you can then just run it locally via a browser

http://localhost:8888/test/tags/invokeArgument.cfc

image

I will give it a try. I am heading out of my office for the night, so will repond tomorrow.

I have not had a chance to dive into testbox. But last weekend I downloaded the Lucee Installer and put it on my developer server. So it is running:

Lucee 6.2.1.122
Apache Tomcat/11.0.6
Java 21.0.7 (Eclipse Adoptium) 64bit
Apache 2.4.62 with reverse proxy ajp configured
on Rocky 9

And did a simple test, and it too, has returned a string for a number, even though it was sent up as a number. I can give you access to this server if you want to poke around.

I have another install on another server that I am testing in, I do not remember what version of Lucee I am running, but I will see if that give the same response and post the specs.

I just tested the same small code on my other dev box, and it also is returning strings. The config on this one is:

Lucee 6.1.1.118 (deployed from WAR)
Tomcat 9.0.97
Java 11.0.25 (Red Hat, Inc.) 64bit
Apache 2.4.62 with reverse proxy ajp
On Rocky 9

Ok, I had a thought. I realize that all your replies and tests are using the cfscript style of coding, where my style is the original cfml. So I wrote 2 tests:

old.cfc:

<cfcomponent>
<cffunction name="testNumbers" output="no" access="remote" returntype="struct">
	<cfargument name="tStr" type="string" required="yes" />
    <cfargument name="tNum" type="numeric" required="yes" />    
   
    <cfreturn arguments />
</cffunction>
</cfcomponent>

test.cfc (I hope this is the same, I have not delved into the script version)

component {
	function testNumbers( required string tStr, required numeric tNum)
    {
    	return arguments
    }
}

And now for test.cfm:

<cfinvoke component="cfc.old" method="testNumbers" returnvariable="r">
	<cfinvokeargument name="tStr" value="string to test" >
    <cfinvokeargument name="tNum" value=1234 >
</cfinvoke>

<cfdump var="#r#" />


<cfscript>
	obj= createObject("component","cfc.test");
	a = invoke( obj, "testNumbers", {tStr="a string to test", tNum=1234});
    writeDump(a);
</cfscript>

And do you want to see the answer? You might not…

Scope Arguments
tStr	1	string	string to test
tNum	2 string	1234

Scope Arguments
tStr	1	string	a string to test
tNum	2 number	1234

And to make it easier on the eyes:
Screenshot 2025-05-18 023534

Something is not right here, or am I mistaken?

<cfinvoke component="cfc.old" method="testNumbers" returnvariable="r">
	<cfinvokeargument name="tStr" value="string to test" >
    <cfinvokeargument name="tNum" value="#1234#" >
</cfinvoke>
<cfset a1=234>
<cfinvoke component="test" method="testNumbers" returnvariable="r">
	<cfinvokeargument name="tStr" value="string to test" >
    <cfinvokeargument name="tNum" value="#a1#" >
</cfinvoke>

try “#1234#” or set to variable result is number