• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

CF2021 vs CF2016 JSON Response Data Types

Explorer ,
Jan 14, 2022 Jan 14, 2022

Copy link to clipboard

Copied

Tried searching to see if anyone has ran across the following issue after upgrading to CF2021. 

 

In CF2016, it "seems" that CF is automatically converting data types based on the key values:

{"message":[],"code":"","success":true,"data":{"ID":15090910}}  Notice the ID is int

 

In CF2021, the data type for the same exact code and request comes back a string:

{"message":[],"code":"","success":true,"data":{"ID":"15090889"}} Notice the ID is a string

 

I've already fixed some that are supposed to be boolean (true/false) rather coming back as ("true" / "false")

 

Is there a new setting I'm not aware of?

Views

481

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jan 17, 2022 Jan 17, 2022

 

Is there a new setting I'm not aware of?


By @--jojo--

Yes. The setting this.serialization.structmetadata was later added to Application.cfc. For details see, for example, my comments in this previous forum thread on serializeJson.

 

If you want "success" to be of boolean type and "ID" to be of integer type throughout the application, then use

 

 

<!--- In Application.cfc --->
<cfset this.serialization.structmetadata = {success:"boolean", ID:"integer">

 

 

Votes

Translate

Translate
Community Expert ,
Jan 17, 2022 Jan 17, 2022

Copy link to clipboard

Copied

 

Is there a new setting I'm not aware of?


By @--jojo--

Yes. The setting this.serialization.structmetadata was later added to Application.cfc. For details see, for example, my comments in this previous forum thread on serializeJson.

 

If you want "success" to be of boolean type and "ID" to be of integer type throughout the application, then use

 

 

<!--- In Application.cfc --->
<cfset this.serialization.structmetadata = {success:"boolean", ID:"integer">

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 18, 2022 Jan 18, 2022

Copy link to clipboard

Copied

@BKBK - that's going to be a pain. Will it have to be just a structure of keys or will it have to match the exact structure of the object being serialized? (e.g. in my example above, ID is nested inside data)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 19, 2022 Jan 19, 2022

Copy link to clipboard

Copied

Hi @--jojo-- ,

I don't think you have to recreate the struct's tree in the setting. With x.y.z.myKey, just a mention of myKey will be sufficient. To be sure, test it yourself.

 

For example, ensure the setting this.serialization.structmetadata is absent from your application. If it is present, comment it out.

 

Run the following code as a CFM page

 

<cfset x = {}>
<cfset x.myVar1 = "1234">
<cfset x.data.myVar2 = "5678">
<cfset x.data.amount1 = "123.45">
<cfset x.data.amount2 = "678.90">
<cfset x.myBool = 'true'>
<cfset x.myStr2 = 'false'>

<cfdump var="#SerializeJSON(x)#" >

 

 

The result should be a JSON in which every key and every value is a string.

 

Now, add the following line to Application.cfc:

 

<cfset this.serialization.structmetadata=
  { myVar2:"integer", 
  	myBool:"boolean", 
  	amount2: "numeric"
  	}>

 

 

Rerun the CFM page.

 

In the resulting JSON the data types of myVar2, myBool and amount2 have changed, respectively, to integer, boolean and numeric. The keys have different locations in the tree structure of the struct.

 

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 19, 2022 Jan 19, 2022

Copy link to clipboard

Copied

That make sense @BKBK. Thank you for the clarification. I guess we'll have to start keeping track of all these keys.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jul 27, 2022 Jul 27, 2022

Copy link to clipboard

Copied

@BKBK  - follow up question regarding this setting - 

given the following setting

 

this.serialization.structmetadata= { itemid:"integer" };

 

 

In some cases the itemid (or whatever else key) could be empty, the serializeJSON function throws an error:

 

Messageempty String
StackTracejava.lang.NumberFormatException: empty String at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:543) at coldfusion.runtime.JSONUtils.serializeJSONMap(JSONUtils.java:707) at coldfusion.runtime.JSONUtils.serializeJSONBase(JSONUtils.java:492) at coldfusion.runtime.JSONUtils.serializeJSONMap(JSONUtils.java:737) at coldfusion.runtime.JSONUtils.serializeJSONBase(JSONUtils.java:492) at coldfusion.runtime.JSONUtils.serializeJSONMap(JSONUtils.java:737) at coldfusion.runtime.JSONUtils.serializeJSONBase(JSONUtils.java:492) at coldfusion.runtime.JSONUtils.serializeJSON(JSONUtils.java:216) at coldfusion.runtime.JSONUtils.serializeJSON(JSONUtils.java:197) at coldfusion.runtime.JSONUtils.serializeJSON(JSONUtils.java:187) at coldfusion.runtime.JSONUtils.serializeJSON(JSONUtils.java:174) at coldfusion.runtime.CFPage.SerializeJSON(CFPage.java:12989) at cfSUGboxAPI2ecfm1975307115.runPage(C:\signupgenius\rocks\SUGboxAPI.cfm:183) at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:257) at coldfusion.tagext.lang.IncludeTag.handlePageInvoke(IncludeTag.java:749) at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:578) at coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:5201) at cfApplication2ecfc1055429981$funcONREQUEST.runFunction(C:\signupgenius\rocks\Application.cfc:211) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:623) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:516) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:95) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:463) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:438) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:310) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:975) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:696) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:503) at coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:115) at coldfusion.runtime.AppEventInvoker.onRequest(AppEventInvoker.java:308) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:569) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:43) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:162) at coldfusion.filter.IpFilter.invoke(IpFilter.java:45) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:97) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:60) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:151) at coldfusion.CfmServlet.service(CfmServlet.java:231) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:311) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:46) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:47) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at coldfusion.inspect.weinre.MobileDeviceDomInspectionFilter.doFilter(MobileDeviceDomInspectionFilter.java:57) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:47) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:377) at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:463) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:834)

 

Is there a way to get around this?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 31, 2022 Jul 31, 2022

Copy link to clipboard

Copied

I don't understand why you would want to by-pass the validation. ColdFusion is doing precisely what you want. The setting 

 

this.serialization.structmetadata= { itemid:"integer" };

 

is you telling ColdFusion that, should it encounter any struct with key itemId, the value must be an integer. 

 

I can think of 3 ways to get around this:

  1.  If it is vital for the key itemId to strictly have an integer value:
        Then use try/catch around any code that involves a struct having key itemId. Handle the error as appropriate in the catch block. That is actually one of the typical use-cases for which this.serialization.structmetadata was introduced.
  2.  If the key itemId may be an integer or empty string, but nothing else:
        Proceed as in 1. Then, within the catch block, validate using something like:
    <cfset myStruct = {}>
    <cfset myStruct.itemId = "">
    
    <cftry>
    	<cfset myJSON = serializeJSON(myStruct)>
    
    	<cfcatch type="any" >
    		<cfif trim(myStruct.itemId) == "">
    			<cfset myStruct.itemId = -1><!--- Or 0, for example: to mean invalid integer --->
    			<cfset myJSON = serializeJSON(myStruct)>
    			<!---<cfdump var="#myJSON#">--->
    		<cfelse>
    			<!--- Handle error: myStruct.itemId is neither integer nor empty string --->
    		</cfif>	
    	</cfcatch>	
    </cftry>​
  3.  If strict, application-wide validation is not required for the key itemId :
        Then you could exclude itemId from this.serialization.structmetadata. If necessary, validate the value at the point where a struct containing itemId is to be serialized.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

@BKBK 

 

So I don't think I explained what I was trying to ask, but you shed light as to why the serializeJSON() throws an error when the value is missing. I didn't realize that defining keys and types using 

this.serialization.structmetadata

 is a strict validation. Basically what I was hoping is that the validation is more like... 

this.serialization.structmetadata = {name:"itemid", type:"integer", required:false}; 

 I know this is not the syntax, but if the value of itemid is empty or null, the validation ignores it.

 

We may have to resort to #3 option as you suggested and just validate the value where needed. 

 

Thanks!

Jojo 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

LATEST

Ah, I see.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation