ColdFusion Query Page returning JSON - json

So I am trying to repurpose an old Coldfusion page for an internal DBA tool to track long running queries.
The page currently does a query as a <CFQUERY name="GetLongRunners"> and then displays the data in a table format:
<table>
<tr>
<td>#GetLongRunners.spid#</td>
<td>#GetLongRunners.Database#</td>
</tr>
</table>
etc, etc
My goal is to strip out all of the display stuff, and be able to simply post to this page, and then receive JSON back with this same data. I played around with:
jsonData = SerializeJSON(#GetLongRunners#)
along with trying to be more specific with #GetLongRunners.database# and it does not seem to be working. The page shows 'jsonData = SerializeJSON(' and I get an error:
Complex object types cannot be converted to simple values.
I'm very new to ColdFusion, and am trying to encapsulate this functionality as much as I can, so I really only have to worry about posting to this page, and then I can get the raw JSON to work with in the front end.
All examples I found, built the queries in a very different way, and it seems to be outside my scope to do it this way.
I am picturing a simple way to serialize the query output as json and send it back as a JSON object. Either that, or build an array by looping through the results of the query, and then serializing that.
Any ideas?
Thanks!

If you are on CF7, try the JSONUtil.cfc. Just download the CFC and install it somewhere under the web root. Then it is ready to use.
Inside your .CFM script, run the query, create an instance of the JSONUtil, and invoke the serializeJSON() method. That is it.
<cfsetting enablecfoutputonly="true">
<cfquery name="GetLongRunners">.... your query here .... </cfquery>
<cfset util = createObject("component", "path.to.JSONUtil")>
<cfcontent type="application/json" reset="true">
<cfoutput>#util.serializeJSON(GetLongRunners)#</cfoutput>
As Henry noted, extra white space can be problem when using .cfm files in this way. Be sure to include the cfsetting at the very top of your script. It will suppress output from everything except content wrapped in <cfoutput> tags.
Truthfully I would use a CFC for this instead, but one thing at a time. If you are interested, this thread has an example of using a remote function as well as converting a query object into a more friendly format ie array of structures.

<cfsetting enablecfoutputonly="true">
<!--- logic/calculation --->
<cfset jsonData = SerializeJSON( GetLongRunners )>
<!--- lastly, output the result --->
<cfoutput>#jsonData#</cfoutput>

Related

How do I parse a JSON from Azure Blob Storage file in Logic App?

I have a JSON file in Azure Blob storage that I need to parse and insert rows into SQL using the Logic App.
I am using the "Get Blob Content" and my first attempt was to then pass to "Parse JSON". It returns and error": InvalidTemplate. Unable to process template language expressions in action 'Parse_JSON' inputs at line '1' and column '2856'"
I found some discussion that indicated that the content needs to be converted to a string so I used "Compose" and edited the code as suggested to
"inputs": "#base64ToString(body('Get_blob_content').$content)"
This works but then the InvalidTemplate issue gets pushed to the Parse function and I get the InvalidTemplate error there. I have tried wrapping the output in JSON expression and a few other things but I just can't get it to parse.
If I take a sample or even the entire JSON and put it into the INPUT of the Parse function it works without issue but it will not accept the blob content as JSON.
The only thing I have been able to do successfully from blob content is to take it as a string and update a row in SQL to later use the OPENJSON in SQL...but I run into an issue there that is for another post.
I am at a loss of what to do.
You don't post much information about your logic app actions, so maybe you could refer to my flow design. I test with a json data with array.
The below is my flow picture. I'm not using compose action, and use decodeBase64(body('Get_blob_content')['$content']) as the Parse Json content.
And if select property from the json, you need set the array index. I set a variable to get a value 'body('Parse_JSON')1['name']'.
you could have a try with this, if still fail, please provide more information or some sample to let us have a test.

How to Parse JSON Returned in ColdFusion

I'm sure this is a relatively simple question, but I can't seem to find a simple answer anywhere online.
I have a few lines of JSON returned by a cfhttp POST with an image URL that I'd like to parse out and display in my ColdFusion page:
{
"href": "http://server.arcgisonline.com/arcgis/rest/directories/arcgisoutput/ESRI_StreetMap_World_2D_MapServer/_ags_map734a6ad322dd493e84499d78f027d841.png",
"width": 854,
"height": 493,
"extent": {
"xmin": -8285407.015562119,
"ymin": 4944008.4197687358,
"xmax": -8220129.7934066672,
"ymax": 4981691.8747132765,
"spatialReference": {
"wkid": 102100,
"latestWkid": 3857
}
},
"scale": 288895.27714399656
}
How can I make "href"'s value a part of a variable in ColdFusion, and/or potentially have a button linked to downloading it?
EDIT: I forgot to mention that I'm using ColdFusion MX - also known as version 6 - and hence why I cannot use the DeserializeJSON listed on Adobe's page
Converts a JSON (JavaScript Object Notation) string data
representation into CFML data, such as a CFML structure or array.
https://wikidocs.adobe.com/wiki/display/coldfusionen/DeserializeJSON
Just parsing your cfhttp result with deserializeJSON()
<cfset getResult = deserializeJSON(result_Variable.filecontent)>
and you can get the href value using "#getResult.href#"
I forgot to mention that I'm using ColdFusion MX
Ah, that makes a very big difference! (Unless otherwise stated in the tags, most people will assume a more recent version, like CF9+).
JSON support was not added until CF8. If you search, there are still some older udf/cfc's for handling JSON out there. For example:
JSONDecode at http://www.cflib.org says it works with MX6
JSONUtil.cfc works with MX7+. It might work with MX6 out of the box, or with a few modifications. This thread has a description of how to encode with JSONUtil. Decoding should be equally simple. Just create an instance and invoke deserializeJSON, ie:
<!--- not tested --->
<cfset util = createObject("component", "path.to.JSONUtil")>
<cfset result = util.deSerializeJSON(yourJSONString)>
That said, ColdFusion MX is a bit long in the tooth and no longer supported. You should seriously consider upgrading or switching to the open source Railo engine.

ColdFusion CFHTTP working with data returned from API

I am just starting to work with the Rotten Tomatoes API to retrieve movie information, and I need some help understanding how to work with the data that is returned. This is my first time working with an API such as this, so please forgive me if this sounds basic.
Using cfhttp I can successfully connect to the API and return search data, but I don't really know what format I am getting back. I thought it was JSON, but using isJSON to check it returns false. I would like to be able to call individual fields within the returned data to populate a query result set that I can output to the user.
The code I am using to make the call is simple:
<cfhttp url="#apiURL#movies.json?apikey=#apiKey#&q=#movieName#" method="get" result="httpResp" timeout="120">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
</cfhttp>
<cfdump var="#httpResp#" />
And the data that is being returned:
I don't expect anyone to give me a complete walk-through of how to build my app, but if someone could give me some pointers as to the proper way to convert the data into a query result, or something else I can use, I would appreciate it.
Edit: Didn't realize the image would be so difficult to read, so here's a cut and paste of the data being returned.
{"total":2,"movies":[{"id":"11029","title":"Krull","year":1983,"mpaa_rating":"PG","runtime":120,"release_dates":{"theater":"1983-07-29","dvd":"2001-04-03"},"ratings":{"critics_rating":"Rotten","critics_score":33,"audience_rating":"Spilled","audience_score":49},"synopsis":"","posters":{"thumbnail":"http://content6.flixster.com/movie/25/86/258696_mob.jpg","profile":"http://content6.flixster.com/movie/25/86/258696_pro.jpg","detailed":"http://content6.flixster.com/movie/25/86/258696_det.jpg","original":"http://content6.flixster.com/movie/25/86/258696_ori.jpg"},"abridged_cast":[{"name":"Ken Marshall","id":"162668719","characters":["Prince Colwyn"]},{"name":"Lysette Anthony","id":"162668720","characters":["Lyssa"]},{"name":"Freddie Jones","id":"162664678","characters":["Ynyr"]},{"name":"Francesca Annis","id":"162688297","characters":["Widow of the Web"]},{"name":"Alun Armstrong","id":"770670461","characters":["Torquil"]}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/11029.json","alternate":"http://www.rottentomatoes.com/m/krull/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/11029/cast.json","clips":"http://api.rottentomatoes.com/api/public/v1.0/movies/11029/clips.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/11029/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/11029/similar.json"}},{"id":"770670060","title":"Bekenntnisse des Hochstaplers Felix Krull (Confessions of Felix Krull)","year":1957,"mpaa_rating":"Unrated","runtime":107,"release_dates":{"theater":"1958-03-04"},"ratings":{"critics_score":-1,"audience_rating":"Spilled","audience_score":33},"synopsis":"","posters":{"thumbnail":"http://content7.flixster.com/movie/10/84/16/10841649_mob.jpg","profile":"http://content7.flixster.com/movie/10/84/16/10841649_pro.jpg","detailed":"http://content7.flixster.com/movie/10/84/16/10841649_det.jpg","original":"http://content7.flixster.com/movie/10/84/16/10841649_ori.jpg"},"abridged_cast":[{"name":"Horst Buchholz","id":"162718595","characters":["Felix Krull"]},{"name":"Liselotte Pulver","id":"326392065","characters":["Zaza"]},{"name":"Ingrid Andree","id":"770670669","characters":["Zouzou"]},{"name":"Susi Nicoletti","id":"770670670","characters":["Madame Houpfle"]},{"name":"Paul Dahlke","id":"573372814","characters":["Professor Kuckuck"]}],"alternate_ids":{"imdb":"0050179"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770670060.json","alternate":"http://www.rottentomatoes.com/m/bekenntnisse-des-hochstaplers-felix-krull-confessions-of-felix-krull/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770670060/cast.json","clips":"http://api.rottentomatoes.com/api/public/v1.0/movies/770670060/clips.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770670060/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770670060/similar.json"}}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Krull&page_limit=30&page=1"},"link_template":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"}
Edit: Thanks, Dan. That was the nudge I needed. After I understood how to get at the JSON data, I was able to find the following explanation of how to turn it into a useful query:Work with remote API JSON data in CF.
The data needs to be deserialized:
<cfset tomatoData=DeserializeJSON(httpResp.filecontent)>
<cfdump var="#tomatoData#">
It looks like the first level in has nothing but structs. So you may be able to
<cfdump var="#tomatoData.total#"> <!--- A single item --->
<cfdump var="#tomatoData.movies#"> <!--- An array --->
The filecontent looks like json. You can refer to it by using
#httpResp.filecontent#.

Coldfusion - Using CFIF with JSON Data

I'm working with a web API, which is returning the following data (this is a cfdump of the cfhttp.filecontent);
{"id":"xxx","service1":["xxx"],"service2":["xxx"]}
I need to be able to read this and determine if a service is on the list. For example,
<cfscript>
pdata = deserializeJSON(cfhttp.FileContent);
</cfscript>
<cfif IsDefined(pdata.service1)>Do something</cfif>
However, I'm receiving an error with the above code. I've only recently started working with JSON, and so far I've had reasonable success - but I'm stuck with this!
Any pointers much appreciated!
It should be IsDefined("pdata.service1")
With isDefined() CF needs to know the name of the variable you are asking about. A name is a string, so you pass in a string.
I found it to be a little counter-intuitive at first, but JasonDean put it into perspective in the comments.

Working with Form Arrays in ColdFusion?

I have no idea how to handle this in ColdFusion 9, I have a form being submitted (POST) with element checkboxes, called items[].
When I do a <cfdump var="#form#" /> no-problem, I get all the items shown with the proper names like items[] eg:
struct
ITEMS[] 13,14
FIELDNAMES ITEMS[]
however doing a <cfdump var="#form.items[]#" /> results in an error. How do I access the CF9 field values? Somehow loop through it?
I cannot seem to do anything with the array to get the id's out of it? Thoughts? I'm kind of stumped and ColdFusion isn't the easiest language to find examples / references on the net. ;)
Is there a correct way to deal with this? I need to get the ID's out of there so I can reference what lines were checked in the form, so I can follow up with an action.
Thanks!
There's no Form Array’s in ColdFusion. Having '[]' at the end doesn't make it an array. You can access the checkbox values from form scope like this:
FORM["ITEMS[]"]
Dot notation doesn't work 'cause of the '[]'. See: http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-7fb2.html
Values from checkboxes are just comma separated values, which is a List in ColdFusion
To loop through it, use cfloop list=:
<cfoutput>
<cfloop index="i" list="#FORM['ITEMS[]']#">
#i#
</cfloop>
</cfoutput>
To convert a list to array, use ListToArray(). There are list functions like listGetAt(), but if you're doing lots of random access, it'd be smarter to convert the list into an array first.
Thoughts, I'm kindof stumped and
coldfusion isn't the easiest language
to find examples / references on the
net ;)
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/index.html
http://learncf.com/tutorials
http://www.easycfm.com/
http://www.carehart.org/ugtv/
I can highly recommend Brian Kotek's "Form Utils" for cases such as this: http://www.briankotek.com/blog/index.cfm/2007/9/4/Implicit-Creation-of-Arrays-and-Structures-from-Form-Fields
I use this in every app I build, because working with arrays and structs on the form submission side is much more preferable to working with lists, imo.
See also the second answer here. It describes how to retrieve values from a field with multiple instances on a form as an array. I have to say though, I've been working in CFML for many years, and I've yet to do this myself, or see it done in any app I've worked on. I think that's just because avoiding commas is very much simpler, but if you can't or don't want to work around it that way, it is possible.
Also, note that in an ajax world, if you json encode the entire body of a post request, rather than individual form fields, it can be any arbitrary data structure, retrievable easily on the server. The snippet below shows how to get to it from ColdFusion. I'm not certain about other languages, but it's almost certainly possible.
To send a post like that using jQuery, JSON.stringify your data before passing it to jQuery, as noted here and here.
If you're building your own ajax request, the punchline would be:
xhr.send(JSON.stringify(data));
To access that data on the server side, this ColdFusion example looks first for that kind json-encoded post body, then a post with json data in the form field 'input', then in a url field with that same name. In all cases, the resulting data gets deserialized and assigned to the local var 'input', which you can then put in request scope, 'rc', or whatever your code expects.
if (Find('application/json', cgi.content_type))
{
input = ToString(GetHttpRequestData().content);
if (IsJSON(input))
input = DeserializeJSON(input);
}
else if (StructKeyExists(form, 'input') and IsJSON(form.input))
input = DeserializeJSON(form.input);
else if (StructKeyExists(url, 'input') and IsJSON(url.input))
input = DeserializeJSON(url.input);
With you list that are Id's it works fine, but if you have an array with comma's in then you're stuck.
In that case you can use the Java method getParameterValues.
<cfdump var="#getPageContext().getRequest().getParameterValues('ITEMS')#">
This will give you an standard CF array which you can use.
For ColdFusion 10+, if you use the sameformfieldsasarray setting in your Application.cfc like this:
component {
this.name = "testingzone2c";
this.sameformfieldsasarray=true;
}
You will get an actual array of form fields with the same name.
ColdFusion 10 Missing Feature - Form Fields and Arrays
I suggest that you remove the "[]" from the name since it disallows dot notation as mentioned in another answer.. When more than one form element contains the same name attribute, the browser will concatenate all of the values into a comma delimited string when submitting the form. Fortunately, ColdFusion has many functions which treat a delimited string as a list. You can use <cfloop> along with these functions to consume the list.