I'm testing an app called Barcode Scanner Terminal for my business; I'm looking to use it as a replacement of sorts for a timeclock.
Employees can scan a barcode or QR code on their ID badge, and this app will send that, along with a timestamp and even GPS coordinates to my server to verify that they're at the right place at the right time. When the phone has an internet connection, this information is passed through via a special URL on my site and I can make it work flawlessly.
The problem?
When there is no internet, the phone stores the scans locally and you can send it to your server later. These scans are stored as a JSON array of structs.
According to the documentation
...Data stored in this manner can be sent to the server as a POST request. I was unsure about how to test all this so I just set some variables, did a scan, and had an email sent to me that dumped the values they represented.
<cfset requestBody = toString( getHttpRequestData().content )/>
Returned this monstrosity and many others like it; what you see below is from one scan.
batch=%5B%7B%22barcode%22%3A%22CSS1959%22%2C%22scannerID%22%3A%223e81b04aa521a05e%22%2C%22time%22%3A%222015-08-11+08%3A28%3A20.419%22%2C%22lat%22%3A32.3999433%2C%22long%22%3A-110.040379%7D%5D
So I ran that value through the URLDecode() function to get something that looks more familiar.
<cfset decodedBody = #URLDecode(requestBody)#>
<!--- This would output the following. Line breaks are for ease of reading. --->
batch=[{"barcode":"CSS1959","scannerID":"3e81b04aa521a05e",
"time":"2015-08-11 08:28:20.419","lat":32.3999433,"long":-110.040379}]
So eventually I had a bunch of scans that formed this Array of Structs in JSON and I have no clue how to handle it.
batch=[
{"barcode":"CSS1035","scannerID":"3e81b04aa521a05e","time":"2015-08-11 08:30:27.232","lat":32.4001579,"long":-110.0403455},
{"barcode":"CSS1959","scannerID":"3e81b04aa521a05e","time":"2015-08-11 08:30:29.366","lat":32.4001579,"long":-110.0403455},
{"barcode":"CSS1649","scannerID":"3e81b04aa521a05e","time":"2015-08-11 08:30:31.642","lat":32.4001579,"long":-110.0403455}
]
I'm TRYING to loop through it and insert them all into a database.
So far I have this and I am getting a JSON parsing error.
<cfset requestBody = toString( getHttpRequestData().content ) />
<cfset decodedBody = #URLDecode(requestBody)#>
<!---This is where I falter because I have no idea how to handle it.--->
<cfset arrayOfStructs = deserializeJson(decodedBody)>
<cfloop array="#arrayOfStructs#" index="barcode">
blah blah query logic
</cfloop>
Thanks!
EDIT: Solved thanks in part to help I received here. Solution below:
<cfset requestBody = #replaceNoCase( toString(getHttpRequestData().content), "batch=", "" )# />
<cfset decodedBody = #URLDecode(requestBody)#>
<cfset ArrayOfStructs = deserializeJson(decodedBody)>
<cfloop array="#ArrayOfStructs#" index="i">
<cfquery name="doodoodoo" datasource="CRM">
INSERT INTO TimeAppTest
(
EmployeeID,
lat,
long,
TimoStampo
)
VALUES
(
'#i.barcode#',
'#i.lat#',
'#i.long#',
'#i.time#'
)
</cfquery>
</cfloop>
It seems to me that you may well be able to access the value of "batch" directly as a part of the form scope. Assuming of course you are really receiving a post request.
So you may well be able to just do:
<cfif isDefined("form.batch")>
<cfset aData = deSerializeJSON(trim(form.batch))>
<cfdump var="#aData#">
</cfif>
So no need to look at the request body and no need to decode the response.
You either need to strip off the "batch=" or pass the entire thing into "evaluate()" which will set the array literal into a variable called batch. I would recommend the former option since the second could be exploited by malicious CFML content in the string.
<cfset arrayOfStructs = deserializeJson( replaceNoCase( decodedBody, "batch=", "" ) )>
来源:https://stackoverflow.com/questions/31977052/json-cfml-looping-over-an-array-of-structs