Stuck with the following problem.
In Coldfusion I have a List:
<cfset myList = "Jack,Mike,Tom,Jude,Dick">
I want to convert myList to a Json in precisely this format :
[
{
"name": [
"Jack",
"Mike",
"Tom",
"Jude",
"Dick"
]
}
]
I have been trying with making a Structure and Array and then use serializeJSON, but it's not giving the format I need.
Any suggestions how to get the required Json format from the list?
Many thanks for any help.
Here you go,
<cfset myList = "Jack,Mike,Tom,Jude,Dick">
<cfset jsonRequired = structNew()>
<cfset jsonRequired.name = listToArray(myList) >
<cfset j = serializeJSON(jsonRequired)>
<cfdump var ="#j#">
This will give you required output.
Edit: From comments below
<cfset myList = "Jack,Mike,Tom,Jude,Dick">
<cfset jsonRequired = [{name = listToArray(myList)}]>
<cfset j = serializeJSON(jsonRequired)>
<cfdump var ="#j#">
Related
I have cffunction that should return JSON structure. There is more than 50 columns that I have to return. Instead of building my structure manually I would like to build that dynamically. So first loop through query then loop through each table column. Here is example:
<cffunction name="getRecords" access="remote" output="true" returnformat="JSON">
<cfargument name="userID" type="string" required="true">
<cfset fnResults = StructNew()>
<cfquery name="myQuery" datasource="test">
SELECT
ur_first,
ur_last,
ur_dob,
ur_gender,
ur_email,
ur_address,
... and the rest of the columns
FROM Users
WHERE ur_id = <cfqueryparam value="#trim(arguments.userID)#" cfsqltype="cf_sql_char" maxlength="15">
ORDER BY ur_createDt
</cfquery>
<cfset fnResults.recordcount = myQuery.recordcount>
<cfloop query="myQuery">
<cfset qryRecs = StructNew()>
<cfloop array="#myQuery.getColumnList()#" index="columnName">
<cfset qryRecs.'#columnName#' = URLEncodedFormat('#columnName#')>
</cfloop>
</cfloop>
<cfset fnResults.data = qryRecs>
<cfreturn fnResults>
</cffunction>
This error I'm getting back after Ajax call:
CFML variable name cannot end with a "." character.
The variable qryRecs. ends with a "." character. You must either provide an additional structure key or delete the "." character.
Referencing to this line:
443 : <cfset qryRecs.'#columnName#' = URLEncodedFormat('#columnName#')>
I want to set column name to structure qryRecs like this:
<cfset qryRecs.ur_first = URLEncodedFormat(myQuery.ur_first)>
This way I don't have to set 50 plus columns manually. They all should be created dynamically. If anyone can help please let me know.
I created an ArrayCollection object that can convert a ColdFusion query to a few different JSON formats. Take a look and see if this fits your needs.
For example, this query:
<cfquery name="rs.q" datasource="cfbookclub">
SELECT DISTINCT
bookid,
title,
genre
FROM
books
WHERE
title LIKE <cfqueryparam value="%#arguments.term#%" cfsqltype="cf_sql_varchar" />
ORDER BY
genre, title
</cfquery>
will be converted to this JSON:
{
"data": [
{
"bookid": 8,
"genre": "Fiction",
"title": "Apparition Man"
},
{
"bookid": 2,
"genre": "Non-fiction",
"title": "Shopping Mart Mania"
}
]
}
I'm also working on an update that adds meta data to the return message:
{
"success": true,
"message": "Array Collection created.",
"meta": {
"offset": 0,
"pageSize": 0,
"totalRecords": 0
},
"data": []
};
I'm attempting to update an existing CF8 application to consume and load an array with the results of a newly updated RESTful API response using OData.
Here's the code in question... After pulling the data from the API that responds with the OData jSON string, the code blows up on the last line that inits the loop
<!--- Returned data is in json format so must change to an array. --->
<cfset local.result = deserializeJSON(myResult)>
<!--- Reference the array collection of categories --->
<cfset local.collection = local.result>
<!--- Initialize the output object --->
<cfset local.output = arrayNew(1)>
<!--- Loop over the collection --->
<cfloop from="1" to="#arrayLen(local.collection)#" index="local.arrayIndex">
...
This was working fine using the previous JSON response:
[
{
"id": 1,
"name": "Blah, blah",
}
]
The only change introduced is the updated JSON response:
[
{
"#odata.context": "string",
"value": [
{
"id": 1,
"name": "Blah, blah"
}
]
}
]
I'm sure I'm missing something basic, but I've never worked on CF before so it's new territory here.
Thoughts?
Thanks!
UPDATE:
Apologies on not providing more detail. Here's how the app currently uses the response:
<!--- Loop over the collection --->
<cfloop from="1" to="#arrayLen(local.collection)#" index="local.arrayIndex">
<!--- Create a reference to the array element --->
<cfset local.objectInstance = local.collection[local.arrayIndex]>
<!--- Create a new object reference --->
<cfset local.thisObject = structNew()>
<!--- Seed the object properties --->
<cfset local.thisObject.categoryId = local.objectInstance.id>
<cfset local.thisObject.categoryName = local.objectInstance.name>
<!--- Place the new object in the collection array --->
<cfset arrayAppend(local.output, duplicate(local.thisObject))>
</cfloop>
And here's the error I'm receiving:
Error Occurred While Processing Request
Object of type class coldfusion.runtime.Struct cannot be used as an array
The error occurred in <path to file> line 97
"Line 97" is the begin loop available in the update above:
I did try using the "newJSON" approach offered by Miguel (thank you very much for that!), but unfortunately, I'm running into the same error.
Thanks again!
-Rich
Update after user posted more information
If you are still getting an error then you did something wrong. You must change the way you are referencing the new JSON data object. I created a new Gist using the updated code that you supplied so you can see how it works - TryCF Gist 2
Basically the code within your <cfloop> needs to look like this. Again, notice that there are actually two <cfloop> blocks. This is because the new JSON format generates an array that contains another array.
<!--- Loop over the collection --->
<cfloop from="1" to="#arrayLen(local.collection)#" index="local.arrayIndex">
<cfloop from="1" to="#arrayLen(local.collection[local.arrayIndex].value)#" index="local.arrayIndex2">
<!--- Create a reference to the array element --->
<cfset local.objectInstance = local.collection[local.arrayIndex].value>
<!--- Create a new object reference --->
<cfset local.thisObject = structNew()>
<!--- Seed the object properties --->
<cfset local.thisObject.categoryId = local.objectInstance[local.arrayIndex2].id>
<cfset local.thisObject.categoryName = local.objectInstance[local.arrayIndex2].name>
<!--- Place the new object in the collection array --->
<cfset arrayAppend(local.output, duplicate(local.thisObject))>
</cfloop>
</cfloop>
See the Gist for more details but this assigns the local.output array as it was before. In your original code the local.objectInstance within the loop was a structure. With the new JSON format the local.objectInstance within the loop now contains an array of structures. So you need to reference it as such.
Original answer before question was updated
With the updated JSON you will need to update how your code references the data (which you did not include in your original post). Making some assumptions I can show you how to reference the data using the examples you gave.
First for your original example. Here is some code that would reference and output the data for you. Notice that I have included a <cfdump> tag. You will want to use that in situations like this where you need to see the data. The deserializeJSON() function parses the JSON for you and creates a ColdFusion array of structures.
<cfset oldJSON = '[ { "id": 1, "name": "Blah, blah" } ]'>
<!--- Returned data is in json format so must change to an array. --->
<cfset local.result = deserializeJSON(oldJSON)>
<!--- Reference the array collection of categories --->
<cfset local.collection = local.result>
<!--- Initialize the output object --->
<cfset local.output = arrayNew(1)>
<cfdump var="#local.result#" label="Old JSON">
<!--- Loop over the collection --->
<cfoutput>
<cfloop from="1" to="#arrayLen(local.collection)#" index="local.arrayIndex">
<p>#local.arrayIndex# - #local.collection[local.arrayIndex].id# - #local.collection[local.arrayIndex].name#</p>
</cfloop>
</cfoutput>
That code gives this output:
Here is an example of the updated code needed to retrieve the same values from the new JSON format. Notice that I added another cfloop to reference the data because there are now two arrays.
<cfset newJSON = '[ { "#odata.context": "string", "value": [ { "id": 1, "name": "Blah, blah" } ] } ]'>
<!--- Returned data is in json format so must change to an array. --->
<cfset local.result = deserializeJSON(newJSON)>
<!--- Reference the array collection of categories --->
<cfset local.collection = local.result>
<!--- Initialize the output object --->
<cfset local.output = arrayNew(1)>
<cfdump var="#local.result#" label="New JSON">
<!--- Loop over the collection --->
<cfoutput>
<cfloop from="1" to="#arrayLen(local.collection)#" index="local.arrayIndex">
<cfloop from="1" to="#arrayLen(local.collection[local.arrayIndex].value)#" index="local.arrayIndex2">
<p>#local.arrayIndex# - #local.arrayIndex2# - #local.collection[local.arrayIndex].value[local.arrayIndex2].id# - #local.collection[local.arrayIndex].value[local.arrayIndex2].name#</p>
</cfloop>
</cfloop>
</cfoutput>
That code gives this output:
I created a gist with all of this code that you can play around with - TryCF Gist 1
I have a piece of JSON (an example):
["12086012800", ["XXX3220210230310", "XXX3220210260120", "XXX3220210170580", "XXX3220210170220", "XXX3220210270310", "XXX3220210080320", "XXX3220210110020", "XXX3220210220530", "XXX3220210020480", "XXX3220210170210", "XXX3220210230160", "XXX3220210060020", "XXX3220210220160", "XXX3220210110130", "XXX3220210021300", "XXX3220210260220", "XXX3220210260590", "XXX3220210210080", "XXX3220210020740", "XXX3220210020780", "XXX3220210270020", "XXX3220210260020", "XXX3220210230290", "XXX3220210260110", "XXX3220210080080", "XXX3220210110010", "XXX3220210220280", "XXX3220210230280", "XXX3220210021040", "XXX3220210220490", "XXX3220210220170", "XXX3220210230530", "XXX3220210020750", "XXX3220210060280", "XXX3220210230790", "XXX3220210230480", "XXX3220210220460", "XXX3220210260010"],
[{
"lat": 25.91026573627833,
"lng": -80.34233093261719
}, {
"lat": 25.909648111101557,
"lng": -80.34602165222168
}, {
"lat": 25.905015819188293,
"lng": -80.34499168395996
}, {
"lat": 25.904243752850498,
"lng": -80.34310340881348
}, {
"lat": 25.906714347345247,
"lng": -80.34147262573242
}, {
"lat": 25.90972531442551,
"lng": -80.34233093261719
}]
]
It comes through to a cfm page from a $.ajax call:
var save = {
poly: function() {
var value = [];
value.push(GEOID);
value.push($.map(selected, function(el) { return el; }));
value.push(getpaths(poly));
console.log(JSON.stringify(value));
$.ajax({
type: "POST",
url: 'data/geoselect_insert.cfm',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(value),
async: false,
dataType: "json",
success: function (location) {
console.log("saved");
}
});
}
}
The cfm page I need to work is similar to below:
<cfsetting showdebugoutput="yes">
<cfheader name="Content-Type" value="application/json">
<CFPARAM name="cookie.UserID" default="0">
<CFPARAM name="PropertySearchID" default="0">
<cfset ParcelJSON = toString( getHttpRequestData().content ) />
<!--- Double-check to make sure it's a JSON value. --->
<cfif isJSON( ParcelJSON )>
<cfset ParcelJSON2 = DeserializeJSON(ParcelJSON, true) >
<cfoutput>#ParcelJSON2[0]#</cfoutput>
</cfif>
I am assuming that ParcelJSON2 is some form of breakout of ParcelJSON.
I need to split JSON into three variables
<cfset Variable1 = (insert wisdom here) > <--"12086012800",
<cfset Variable2 = (insert wisdom here) > <--["XXX3220210230310","X...]
<cfset Variable3 = (insert wisdom here) > <--["lat":"23.9999"......]
I want to perfrom an cfquery insert to put those values in.
how do I break the incoming JSON without breaking the child JSONs. Each Child JSON is a value of their own.
Any wisdom would be greatly appreciated
Often in this case, I find solace in visualizing my data. Thanks to ColdFusion, it's simple. Directly after your call to DeserializeJSON, dump the data so you can see it.
<cfdump var="#ParcelJSON2#">
At this point you'll see a nicely formatted ColdFusion dump of data that you can get, output and manipulate as you see fit.
<cfset Variable1 = ParcelJSON[1] />
<cfset Variable2 = ParcelJSON[2] />
<cfset Variable3 = ParcelJSON[3] />
If you need to get JSON back out of the CF variables, you can reverse part of the process.
<cfset Variable1 = serializeJSON(ParcelJSON[1]) />
<cfset Variable2 = serializeJSON(ParcelJSON[2]) />
<cfset Variable3 = serializeJSON(ParcelJSON[3]) />
Finally, to see that it's working the way you want it, try dumping again:
<cfdump var="#variables#">
After you have deserialized your json its just ends up combination of arrays and structs. In your case an array of complex objects.
So if the JSON you receive is always in the same format.
I noticed in your example you use Zero to reference the first element in CFML arrays start at One (unlike almost every other language).
So something like:
<cfset Variable1 = ParcelJSON2[1]> <--"12086012800",
<cfset Variable2 = ParcelJSON2[2] > <--["XXX3220210230310","X...]
<cfset Variable3 = ParcelJSON2[3] > <--["lat":"23.9999"......]
I'm using this code
<cfset user_data = StructNew() />
<cfset user_data[["field_a"]["und"]["tid"] = '123' />
<cfset json = SerializeJSON(user_data)>
It generates this json
{"und":{"tid":123}}
I would like to have the json look like this instead
{"und":[{"tid":123}]}
How do I have to change the struct?
Use the following cfscript:
user_data = { 'und' = [ { 'tid' = '123' } ] };
json = serializeJSON(user_data);
you're not putting the key/value pair in an array as needed by your request.
I'm trying to use ColdFusion's SerializeJSON() to return JSON data.
So far I have done this:
<cfset rows = [] />
<cfloop query="rsProducts">
<!--- Create a row struct. --->
<cfset row = {} />
<!--- Add each column to our struct. --->
<cfloop
index="column"
list="#rsProducts.columnList#"
delimiters=",">
<cfset row[ column ] = rsProducts[ column ][ rsProducts.currentRow ] />
</cfloop>
<!--- Append the row struct to the row array. --->
<cfset arrayAppend( rows, row ) />
</cfloop>
<cfreturn SerializeJSON(rows, true)>
This works fine and produces JSON like this:
[Object {PRICE: 89.99, PRODUCTSTATUS: 1, COUNTRY: US}, Object {PRICE: 110.50, PRODUCTSTATUS: 4, COUNTRY: UK}, Object {PRICE: 41.20, PRODUCTSTATUS: 1, COUNTRY: IN}]
However instead of a label of "Object" for each item, I'd like it to be "ProductItem" instead. It just makes it easier for me to deal with in jQuery later on.
How could I have it so it labels each object in JSON as "ProductItem"?
You can loop over the data in this manner easily.
.success(function(data) {
var ProductItem = JSON.parse(data);
$.each(ProductItem,function(key,value){
console.log(value.PRICE +" "+ value.PRODUCTSTATUS + " " + value.COUNTRY);
});