Mark Berning
05/23/2023, 5:19 PM<cfset date = "05/10/2023">
<cfset hoursPerDay = 4.0> <!--- should be numeric --->
<cfset data = $[Schedule_Date = date, Schedule_Hours = hoursPerDay]> <!--- I want Schedule_Date and Schedule_Hours to be case sensitive not converted to uppercase ---> <!--- shortcut for case sensitive structure ${ --->
<cfset metadata = {Schedule_Hours:"numeric"}>
<cfset data.setMetadata(metadata)>
<cfoutput>
#serializeJSON(data)#
</cfoutput>
get this error:
An exception occurred while calling the function setMetaData.
Cannot cast coldfusion.runtime.OrderedCaseSensitiveStruct to coldfusion.runtime.Struct
If you want me to show the non-implicit struct format and/or script based method I can, but get the same error regardless. You can not serialize a case sensitive structure and set the metadata to be numeric at the same time. Also this is in a component and the hoursPerDay is passed in as a numeric cfargument, it is not a simple 4.0 shown above.sknowlton
05/23/2023, 5:23 PM$[]
syntax before.
What happens if you do:
someStruct = {
'Schedule_Date' : date,
'Schedule_Hours' : hoursPerDay
}
There is a CF admin setting for preserving case in serialization, but in my experience even if it's off, if you do 'attr' : 'value'
instead of attr : 'value'
you'll get the serialization you wantTim
05/23/2023, 5:29 PMdata["Schedule_Date"] = date
. I think the important part is making sure that the struct keys are referenced as strings.Mark Berning
05/23/2023, 5:29 PMTim
05/23/2023, 5:30 PM{"key": value}
syntax because it starts out as basically JSON already.sknowlton
05/23/2023, 5:31 PMsetMetadata
line, also?Tim
05/23/2023, 5:32 PMsknowlton
05/23/2023, 5:32 PMTim
05/23/2023, 5:32 PMMark Berning
05/23/2023, 5:32 PMsknowlton
05/23/2023, 5:33 PMMark Berning
05/23/2023, 5:34 PMTim
05/23/2023, 5:36 PMMark Berning
05/23/2023, 5:37 PMTim
05/23/2023, 5:37 PMSchedule_Hours:{type: "numeric", name:"Schedule_Hours"}
Mark Berning
05/23/2023, 5:40 PMMark Berning
05/23/2023, 5:41 PMsknowlton
05/23/2023, 5:42 PMsetMetaData
which is arguably Lucee's problem and not yours, but when possible, one best practice is to avoid engine-specific code (though it seems like they might tackle it for Lucee 6) so maybe forget about this consideration for now
this seems like domain logic, so it should probably be in a service layer and in script rather than in tags; or in a model.
are you using a framework? if not, you're already bit far afield from best practices, though probably somebody will fight me on thatsknowlton
05/23/2023, 5:43 PMTim
05/23/2023, 5:43 PMMatt Jones
05/23/2023, 5:43 PMdata = {"Schedule_Date": date, "Schedule_Hours": hoursPerDay}
Tim
05/23/2023, 5:44 PMsknowlton
05/23/2023, 5:44 PMsknowlton
05/23/2023, 5:44 PMsetMetaData
either if only some structs and not others allow itMark Berning
05/23/2023, 5:44 PMTim
05/23/2023, 5:45 PMTim
05/23/2023, 5:45 PMMark Berning
05/23/2023, 5:47 PMMatt Jones
05/23/2023, 5:47 PMMatt Jones
05/23/2023, 5:47 PMMark Berning
05/23/2023, 5:48 PMAdam Cameron
<cfset date = "05/10/2023">
<cfset hoursPerDay = 4.0> <!--- should be numeric --->
<cfset data = {"Schedule_Date" = date, "Schedule_Hours" = hoursPerDay}>
<cfoutput>
#serializeJSON(data)#
</cfoutput>
You've clocked the thing about using strings to create case-sensitive identifiers; but if yer value is numeric, if will serialise as numeric without any dicking around with metadata.
More seriously though, DD|MM/MM|DD/YYYY
is not a great string format to use as a date. I presume that's mm/dd/yyyy
as there are more USAns here than anyone else, but that format is idiosyncratic to USAn humans. It's not really a date format used for anything else. Nothing sane anyhow ;-). Yer better off using some ISO-8601 format for date->string formatting, or perhaps RFC-822. Or, indeed, use an actual Date in the CFML code, and let the CFML engine take care of it for you. That is all part of the serialisation process as well.Adam Cameron
Mark Berning
05/23/2023, 7:30 PMbdw429s
05/24/2023, 1:55 PMAdam Cameron
Mark Berning
05/24/2023, 2:24 PMhoursPerDay
should be numeric in the JSON output (no quotes).
<cffunction name="genSchedule" access="public" output="true" returntype="struct" >
<cfargument name="startdate" type="date" required="true">
<cfargument name="endDate" type="date" required="true">
<cfargument name="FF_Project_Id" type="string" required="true">
<cfargument name="hoursPerDay" type="numeric" required="true" default="8.0">
<cfargument name="FF_Contact_Id" type="string" required="false" default="">
<cfargument name="Webkey_Id" type="string" required="true">
<cfargument name="AdvDates" type="string" required="false" default="">
<cfargument name="EventID" type="numeric" required="true">
<cfset error ="">
<cfset startdate= parseDateTime(arguments.startdate)>
<cfset enddate= parseDateTime(arguments.enddate)>
<cfset ddiff = DateDiff("d",startdate,enddate)+1>
<cfset dayoffset = 1-DayOfWeek(startdate)>
<cfset wdiff = Week(enddate)-Week(startdate)+1+((Year(enddate)-Year(startdate))*53)>
<cfset result = StructNew("casesensitive")>
<cfset week = StructNew()>
<cfset Schedules = ArrayNew(1)>
<cfset AdvancedDates = ArrayNew(1)>
<cfset metadata = {Schedule_Hours:"numeric"}>
<cftry>
<cfif arguments.AdvDates eq "">
<cfloop index="wk" from="1" to="#wdiff#">
<cfset wkStart ="">
<cfset wkEnd ="">
<cfset cnt = 0>
<cfset totHours = 0>
<cfloop index="day" from="1" to="7">
<cfset date=dateFormat(DateAdd('d',dayoffset,startdate),"yyyy-mm-dd")>
<cfif date gte startdate AND date lte enddate AND IsValid("range",DayOfWeek(date),2,6)>
<cfif wkStart eq ""><cfset wkStart=date> </cfif>
<cfset wkEnd = date>
<cfset data = ['Schedule_Date' = date, 'Schedule_Hours' = arguments.hoursPerDay]>
<cfset data.setMetadata(metadata)>
<cfset totHours += arguments.hoursPerDay>
<cfset AdvancedDates[++cnt] = data>
<cfset Schedules[wk]['AdvancedDates'] = AdvancedDates>
</cfif>
<cfset dayoffset++>
</cfloop>
<cfif wkStart neq "">
<cfset Schedules[wk]['End_Date'] = wkEnd>
<cfset Schedules[wk]['Start_Date'] = wkStart>
<cfset Schedules[wk]['FF_Project_Id'] = arguments.FF_Project_Id>
<cfset Schedules[wk]['Start_Date'] = wkStart>
<cfset Schedules[wk]['Total_Hours'] = totHours>
<cfset Schedules[wk]['EventID'] = arguments.EventID>
</cfif>
</cfloop>
<cfelse>
<cfloop list="#arguments.AdvDates#" item="wk" delimiters=";" index="w">
<cfset wkStart ="">
<cfset wkEnd ="">
<cfset cnt = 0>
<cfset totHours = 0>
<cfloop list="#wk#" item="date">
<cfset date = dateFormat(date,"yyyy-mm-dd")>
<cfif wkStart eq ""><cfset wkStart=date> </cfif>
<cfset wkEnd = date>
<cfset data = ['Schedule_Date' = date, 'Schedule_Hours' = arguments.hoursPerDay]>
<cfset data.setMetadata(metadata)>
<cfset totHours += arguments.hoursPerDay>
<cfset AdvancedDates[++cnt] = data>
<cfset Schedules[w]['AdvancedDates'] = AdvancedDates>
</cfloop>
<cfif wkStart neq "">
<cfset Schedules[w]['End_Date'] = wkEnd>
<cfset Schedules[w]['Start_Date'] = wkStart>
<cfset Schedules[w]['FF_Project_Id'] = arguments.FF_Project_Id>
<cfset Schedules[w]['Start_Date'] = wkStart>
<cfset Schedules[w]['Total_Hours'] = totHours>
<cfset Schedules[w]['EventID'] = arguments.EventID>
</cfif>
</cfloop>
</cfif>
<cfset retJSON = ${"Webkey_Id":arguments.Webkey_Id,"FF_Contact_Id":arguments.FF_Contact_Id}>
<cfset retJSON.Schedules = Schedules>
<cfset result.data = retJSON>
<cfset result.data_JSON = serializeJSON(retJSON)>
<cfcatch>
<cfset error = cfcatch.message>
</cfcatch>
</cftry>
<cfset result.error = error>
<cfreturn result>
</cffunction>
Mark Berning
05/24/2023, 2:26 PMMark Berning
05/24/2023, 2:29 PMhoursPerDay
becomes a quoted value and not a numeric value during serializeJSON function.Tim
05/24/2023, 2:32 PMAdam Cameron
Mark Berning
05/24/2023, 2:36 PMMark Berning
05/24/2023, 2:36 PMvar*1
or cast itbdw429s
05/24/2023, 2:37 PMval()
is the best way
https://trycf.com/gist/7cd3bad6407c78ad0c6fed0a4e3db0e2/acf2021?theme=monokaiAdam Cameron
"8.0"
is interpreted as a string.
You need to make sure the values are actually numeric (ie: ints or floats as appropriate).
But this does answer your question. I still agree with Brad though: forget the metadata, and just coerce the value into a numeric when sticking the value into the structAdam Cameron
val
would work wouldn't it?bdw429s
05/24/2023, 2:38 PMnum+0
will do it too. I actually do this in CFConfig when writing WDDXbdw429s
05/24/2023, 2:39 PMAdam Cameron
val
is the more emphatic / clear approach here. There's no "why's he multiplying this by one/adding zero?"Adam Cameron
Mark Berning
05/24/2023, 2:41 PMbdw429s
05/24/2023, 2:41 PMTim
05/24/2023, 2:42 PM<cfset
every line is so worth it. 🙂Adam Cameron
Mark Berning
05/24/2023, 2:44 PMAdam Cameron
<cfmail>
call I fed it the other day. Meant to raise an issue with... PeteF?... about that.
I reckon it's definitely good for 80% of stuff though.