Using the array notation for creating the keys in a struct used to preserve the case of the key.
<cfset var response = structNew()>
<cfset response[ "error" ] = 0>
<cfset response[ "message" ] = "">
<!--- this worked when converting this struct to a JSON
So when I actually put some data into the struct:
<cfset response.error = 1>
<cfset response.message = "There was an error inserting the record...">
I surprised when I saw this come across the firebug console:
{"MESSAGE":"There was an error inserting the record...","ERROR":1}
note, the information is what I was expecting to see.
I understand if I would have used <cfset response.error = 0>, for the case not to be preserved when converting it to a JSON, but this has worked for me in the past. Am I doing something wrong that I'm blind to or did something change in CF10?
EDIT:
Before all of the responses came back, I tried what everyone said.
<cfset response["error"] = 1>
<cfset response["message"] = "There was an error inserting the record...">
and it worked. So, I'm guessing they changed how serializeJSON works in CF10.
Good to know.
If you continue to reference the struct key with bracket notation rather than dot notation, you should have no issue with case when using serializeJSON().
After testing on CF9, however, it seems to work fine whether I use bracket- or dot-notation. This may be a difference between CF9 and 10 and, as Ray recommends, you may want to file a bug report for it.
Here's what I did in CF9:
<cfset response = structNew()>
<cfset response[ "error" ] = 0>
<cfset response[ "message" ] = "">
<!--- this worked when converting this struct to a JSON --->
<cfoutput>#serializeJSON(response)#</cfoutput><br /><br />
<!--- This outputs {"message":"","error":0} --->
<cfset response.error = 1>
<cfset response.message = "There was an error inserting the record...">
<cfoutput>#serializeJSON(response)#</cfoutput>
<!--- This outputs {"message":"There was an error inserting the record...","error":1} --->
I believe if you continue to use bracket notation it will continue to work ok. A bit more typing I guess, but should work. If this is a change from CF9 though you may want to file a bug report.
Related
I need to use the FilegetMimeType() function, and I tested it in a program called demomimetype.cfm.
<cfoutput>
<cfset reploc = '#cookie.moxlog#'>
<cfset extrepoc = ExpandPath('#reploc#')>
<cfset typegif = FilegetMimeType('#extrepoc#/brightpink1.gif')>
typegif brightpink1.gif #typegif#<br>
</cfoutput>
This program returns the result that typegif is "image/gif" which is exactly correct. When I add the lines
<cfheader name = "Content-Disposition" value="attachment;#extrepoc#/logo106">
<cfcontent type="#typegif#" file="#extrepoc#/brightpink1.gif">
I get this result:
This is what I was hoping for, although demomimetype.cfm is not what I chose to open. However, this screen does open brightpink1.gif, so I'm okay with it.
Then I tried to integrate this into my actual system using this program, which results from a submit in an earlier program:
<cfoutput>
<cfset col = form.thecol>
<cfset colarray = getPageContext().getRequest().getParameterValues('xcol')>
<cfset origval = getPageContext().getRequest().getParameterValues('#col#')>
<cfset attname = origval[1]>
<cfset extreploc = ExpandPath("#cookie.moxlog#")>
<cfset typeatt = FilegetMimeType('#extreploc#/#attname#')>
</cfoutput>
The variable "attname" will be "brightpink1.gif. When I output typeatt I get "application/octet-stream", which is not correct. And when I add the lines
<cfheader name = "Content-Disposition" value="attachment;#extreploc#/#attname#">
<cfcontent type="#typeatt#" file="#extreploc#/#attname#">
I get the wrong result -- not surprising because the mimetype is wrong:
Obviously the demo is working correctly, and the real application is not. I have tried making the filename in the demo to be a variable, and the demo goes on working. I have tried making the filename in the application specific, and it still does not work.
I don't want to use the "strict" parameter because some of the files do not have extensions, even though they are of a specific type like .jpg.
There must be some reason why the code in the demo works and the nearly identical code in the application does not. But I cannot see it. Can anyone figure out what is going on here?
I am trying to create an array of structures, in my Application.cfm file, which can then be appended to in further pages. I am following the EasyCFM tutorial #173 by Charlie. I am using it this way:
<cfset session.box_status = arrayNew(1) />
<cfset session.box_status[1] = structNew() />
<cfset session.box_status[1].partner_id = '0' />
<cfset session.box_status[1].partner_username = '' />
<cfset session.box_status[1].status = '0' />
In my page, I am appending to the structure like so:
<cfloop from="1" to="#arrayLen(session.box_status)#" index="i">
<cfset session.box_status[i].partner_id = ArrayAppend(i,FORM.partner_id) />
<cfset session.box_status[i].partner_username = ArrayAppend(i,FORM.partner_username) />
<cfset session.box_status[i].status = ArrayAppend(i,FORM.box_status) />
</cfloop>
But am getting an error:
The web site you are accessing has experienced an unexpected error.
Please contact the website administrator.
The following information is meant for the website developer for debugging purposes.
Error Occurred While Processing Request
Object of type class java.lang.Double cannot be used as an array
In addition to Scott's comments, you need to clarify what you are actually trying to achieve. The question asks about appending a new item, yet it looks as if parts of your code attempt to overwrite the existing structure values in position session.box_status[1].
If you really want to append a new structure to the array, there is no reason to loop. Simply create an empty structure:
<cfset newItem = structNew() />
... populate it with some values:
<cfset newItem.partner_id = FORM.partner_id>
... etcetera
Then append the new structure to the array. Notice, the code below does not care about the result of ArrayAppend. That is because the function modifies the array in place, and only returns true/false depending on whether the action was successful.
<cfset ArrayAppend(session.box_status, newItem)>
Update:
That said, the tutorial you are using was obviously written for an older version of CF. As #cfqueryparam pointed out, later versions support a shorthand for creating arrays and structures. Instead of using structNew(), you could simply do this:
<cfset newItem = { partner_id = FORM.partner_id, ... etectera }>
The first argument in arrayAppend() needs to be the array to which you are appending something, in your example, you are using i - which is the counter of your loop - which is a number, not an array.
Note that a common error is to pass the array name, but forget to put the pound symbols. For me, when I make the error of saying
<cfloop array="myAry" index="aryElement">
instead of the proper expression
<cfloop array="#myAry#" index="aryElement">
then the debug message java.lang.string cannot be used as an array is issued.
My customer is encountering the error The 2 parameter of the Left function, which is now -1, must be a positive integer after migrating from ColdFusion 8 to ColdFusion 10. The page performs as expected in Firefox 31 and Chrome 36 on Windows 7. However, this error occurs in IE9 but not IE7. Are there different security settings in IE9 that prohibit the processing of the code?
The snippet of code in question is:
<!--- Populate the UserInfo struct --->
<cfloop INDEX="item" LIST="#COOKIE.MYELVIS_USERINFO#" DELIMITERS="&">
<cfset delim = #FindOneOf("=",item)#>
<cfif (len(item)-delim)>
<cfset UserInfo[UCase(left(item,delim-1))] = right(item,len(item)-delim)>
<cfelse>
<cfset UserInfo[UCase(left(item,delim-1))] = "">
</cfif>
</cfloop>
I'm torn to say it's a code error when it works in other browsers, just not IE9. Any thoughts? Thank you.
Perhaps have him clear cookies, he might have a holdover from cf 8 and perhaps the two versions encode differently. It looks like, if this is possible, one of the values doesn't contain a =.
Upon reviewing your code, I think this is what you need.
<cfloop INDEX="item" LIST="#COOKIE.MYELVIS_USERINFO#" DELIMITERS="&">
<cfset delim = #FindOneOf("=",item)#>
<cfif (delim) and (len(item)-delim)>
<cfset UserInfo[UCase(left(item,delim-1))] = right(item,len(item)-delim)>
<cfelse>
<cfset UserInfo[UCase(item)] = "">
</cfif>
</cfloop>
I recently upgraded a system from CF8 to CF10 and have one bug that I'm having problems tracking down. It has to do with a remote API call that gets a JSON string back and that string then gets converted to a query object. That's where I'm coming across the error:
Element [n] is undefined in a Java object of type class coldfusion.runtime.Array. The problem is in the function that converts the string to a query.
<cffunction name="CFjsonToQuery" access="public" returntype="query" output="no">
<cfargument name="cfData" required="yes" type="struct"/>
<cfset var LOCAL = {}/>
<cfset LOCAL.tmpQry = QueryNew( ArrayToList(ARGUMENTS.cfData.Data.COLUMNS) ) />
<cfloop index = "i" from = "1" to = "#ArrayLen(ARGUMENTS.cfData.Data.DATA)#">
<cfset LOCAL.Row = QueryAddRow(LOCAL.tmpQry) />
<cfloop index="k" from="1" to="#ArrayLen(ARGUMENTS.cfData.Data.DATA[i])#">
<cfset LOCAL.colName = ARGUMENTS.cfData.Data.COLUMNS[K]/>
<cfset QuerySetCell(LOCAL.tmpQry,LOCAL.colName,ARGUMENTS.cfData.Data.DATA[i][k],LOCAL.Row)/>
</cfloop>
</cfloop>
<cfreturn LOCAL.tmpQry/>
</cffunction>
Anywhere the JSON returns 'null' (i.e. "...","19107-3609",null,null,null,"...") the error is thrown. I've tried using isNull to check if it's null in the cfloop:
<cfif isNull(ARGUMENTS.cfData.Data.DATA[i][k])>
<cfset ARGUMENTS.cfData.Data.DATA[i][k] = 'I AM NULL'/>
</cfif>
EDIT - here's a simplified example - the issue is the way the newer deserializeJson() works I believe:
<cfset jstr = '{"SUCCESS":true,"ERRORS":[],"DATA":{"COLUMNS":["ID","FNAME","LNAME"],"DATA":[[390132,"steve",null]]}}'/>
<cfset cfData = deserializeJson(jstr) />
<cfloop index = "i" from = "1" to = "#ArrayLen(cfData.Data.DATA)#">
<cfset Row = QueryAddRow(tmpQry) />
<cfloop index="k" from="1" to="#ArrayLen(cfData.Data.DATA[i])#">
<cfset colName = cfData.Data.COLUMNS[K]/>
<cfset QuerySetCell(tmpQry,colName,cfData.Data.DATA[i][k],Row)/>
</cfloop>
</cfloop>
I've tried all sorts of tests for empty string, isNull etc. and I'm still not sure how to get the query object built if deserializejson returns:
[undefined array element] Element 3 is undefined in a Java object of type class coldfusion.runtime.Array.
This does seem to work:
<cfset cfData = deserializeJson(returnData,'FALSE') />
<cfset qryData = cfData.data />
This lets me then use qryData as if it were a normal cfquery.
You can do a check if the element is undefined using the CF Function ArrayIsDefined(array, elementIndex)
What I've done for now is add 'FALSE' to the deserializeJSON strictMapping flag and that seems to automatically create a query object? I'll admit though this is getting into the underpinnings of CF10 and I could be wrong on that. I'll update my code above for visual clarity.
So, I ran into an odd bug which I cannot figure out in CF9. It appears to be caused by using a struct literal, inside a function call, inside an if statement, inside a loop. Remove any one of these variables and the condition does not occur.
The following code throws an error:
Error: Variable KEY is undefined.
<cffunction name="test">
<cfreturn true>
</cffunction>
<cfset local.data = { first = "asdf" }>
<cfloop list="first" index="key">
<cfif test({ name = local.data[key] })>
<cfoutput>test</cfoutput>
</cfif>
</cfloop>
Why? If we set the struct to a variable it works. If we do not loop it works just fine as well.
<cffunction name="test">
<cfreturn true>
</cffunction>
<cfset local.data = { first = "asdf" }>
<cfset key = "first">
<cfif test({ name = local.data[key] })>
<cfoutput>test</cfoutput>
</cfif>
Any ideas what is going?
I'll give a better answer once you give a better question ;-) (just tell us the error message as per my comment), but the fact of the matter is that CF's implementation of struct-literal (and array-literal) notation has been blighted by a long list of implementation bugs. I think they have finally been ironed out in CF10.
So, to answer your question slightly obliquely: "what's going on?" Shonky coding in ColdFusion is going on.
What's the fix? When you encounter these problems, use traditional struct notation instead (dot notation or associative array notation).
There's nowt better to do about it other than that, I'm afraid.
Also look in the bug base to see if your particular case has already been logged, and if not: log a new bug.