Coldfusion Json from structure - json

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.

Related

Coldfusion convert List to Json

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#">

how do I change the label for each object in SerializeJSON

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);
});

ColdFusion: how to check whether JSON property is null?

Let's say I POST this simple JSON payload:
{"foo":null}
On the ColdFusion server, how do I check if the 'foo' property is null?
IsDefined won't work because it will be false for null values. IsNull won't work because IsNull will be true for not just null values, but also for missing properties.
<cfset json = DeserializeJSON(GetHttpRequestData().content) />
<cfdump var="#IsDefined("json.foo")#" /> <!--- false --->
<cfdump var="#IsNull(json.foo)#" /> <!--- true --->
<cfdump var="#IsNull(json.bar)#" /> <!--- true --->
My mistake, I thought null in JSON would be deserialized to empty string, but it's not true.
null in JSON is translated to be struct with key foo but undefined in CF10. (not sure about older CF version)
Therefore, a true isStructValueNull() can be written like this:
function isStructValueNull(struct, key) {
return listFind(structKeyList(struct), key)
&& !structKeyExists(struct, key);
}
json = deserializeJSON('{"foo":null,"bar":123}');
writeDump(isStructValueNull(json, "foo")); // yes
writeDump(isStructValueNull(json, "bar")); // no
or you can loop through json and use structKeyExists(), if it's false, it's null.
function structNullKeyList(struct) {
var nulls = "";
for (var key in struct)
if (!structKeyExists(struct, key))
nulls = listAppend(nulls, key);
return nulls;
}
writeDump(structNullKeyList(json)); // 'foo'
How are you posting this data? What do you get when you dump just the variable "json"?
If you're POSTing data to ColdFusion, each parameter should get converted to a FORM scoped variable. Check the headers of your HTTP POST to see how the data is being sent.
If they're being sent as individual parameters, you should be able to get check <cfif structKeyExists(form, "foo")> and then check to see if the value of form.foo is an empty string. (ColdFusion translates a NULL value to an empty string.)
I use Raillo.
Railo 4.1.3.005 Error (expression)
Message the value from key [FOO] is NULL, which is the same as not existing in CFML.
But we can use Full Null suport. Where it can be properly examined, as you want.
<cfscript>
objectValues = { 'one' : 1 , 'two' : 2 , 'three' : JavaCast( "null", 0 ) , 'four' : null };
dump(objectValues);
// Known existing attribute
dump('three');
dump( isDefined('objectValues.three') );
dump( isNull(objectValues.three) );
dump( StructKeyExists(objectValues,'three') );
// Known Railo Null value
dump('four');
dump( isDefined('objectValues.four') );
dump( isNull(objectValues.four) );
dump( StructKeyExists(objectValues,'four') );
// Unknown existing attribute
dump('five');
dump( isDefined('objectValues.five') );
dump( isNull(objectValues.five) );
dump( StructKeyExists(objectValues,'five') );
</cfscript>
What's your ColdFusion Version?
Actually a true JSON null value should be translated to 'null' by Coldfusion which is equally annoying but manageable
If you store just an empty string in the struct like this:
<cfset s = StructNew()>
<cfset s.test = "" />
<cfset json = SerializeJSON(s)>
<cfdump var="#json#">
<cfset d = DeserializeJSON(json)>
<cfdump var="#d#">
You get the following json: {"TEST":""}
and d.test is ""
But if you explicitly store a java null in the struct like this:
<cfset s = StructNew()>
<cfset s.test = javaCast( "null", "" ) />
<cfset json = serializeJSON(s)>
<cfdump var="#json#">
<cfset d = DeserializeJSON(json)>
<cfdump var="#d#">
you get the following json value: {"TEST":null}
and d.test is 'null'
This is probably more preferable as you could do this:
<cfif StructKeyExists(d,"TEST") AND Compare(d.test,"null") IS 0>

Convert coldfusion json to struct

I have a JSON variable output from a jQuery application as so:
[{"id":1},
{"id":197,"children":[{"id":198},{"id":199},{"id":200}]},
{"id":2,"children":[{"id":3},{"id":4},{"id":143},{"id":6},{"id":5},{"id":7},{"id":8},{"id":9},{"id":10},{"id":11},{"id":12}]},
{"id":15,"children":[{"id":17},{"id":190},{"id":191},{"id":131},{"id":16},{"id":142},{"id":124}]},
{"id":149,"children":[{"id":150},{"id":160},{"id":161},{"id":184}]},
{"id":20,"children":[{"id":132},{"id":127},{"id":152},{"id":107},{"id":108},{"id":109},{"id":110},{"id":125},{"id":128},{"id":130},{"id":129},{"id":112}]},
{"id":162,"children":[{"id":163},{"id":164},{"id":165},{"id":166},{"id":186},{"id":187}]},
{"id":167,"children":[{"id":173},{"id":168},{"id":170},{"id":169},{"id":192},{"id":194}]},
{"id":174,"children":[{"id":176},{"id":175},{"id":188}]},
{"id":153,"children":[{"id":178},{"id":179},{"id":195},{"id":154},{"id":157}]},
{"id":180,"children":[{"id":181},{"id":182},{"id":183},{"id":189}]},
{"id":122},
{"id":21},
{"id":13},
{"id":92},
{"id":22},
{"id":113},
{"id":114}]
I need to convert this variable to a struct and then loop the struct by the first id parameter to find the children for each id (if there is one). I have tried to convert it as a structure like so but I am getting an error:
<cfset jsonarray = deserializeJson(output)>
<cfloop collection="#jsonarray#" index="id">
<cfdump var="#jsonarray[id]#">
</cfloop>
It does not recognize the variable as a structure:
Invalid collection [{id={1}}, {children={[{id={198}}, {id={199}}, {id={200}}]},id={197}}, {children={[{id={3}}, {id={143}}, {id={4}}, {id={6}}, {id={5}}, {id={7}}, {id={8}}, {id={9}}, {id={10}}, {id={11}}, {id={12}}]},id={2}}, {children={[{id={17}}, {id={190}}, {id={191}}, {id={131}}, {id={16}}, {id={142}}, {id={124}}]},id={15}}, {children={[{id={150}}, {id={160}}, {id={161}}, {id={184}}]},id={149}}, {children={[{id={132}}, {id={127}}, {id={152}}, {id={107}}, {id={108}}, {id={109}}, {id={110}}, {id={125}}, {id={128}}, {id={130}}, {id={129}}, {id={112}}]},id={20}}, {children={[{id={163}}, {id={164}}, {id={165}}, {id={166}}, {id={186}}, {id={187}}]},id={162}}, {children={[{id={173}}, {id={168}}, {id={170}}, {id={169}}, {id={192}}, {id={194}}]},id={167}}, {children={[{id={176}}, {id={175}}, {id={188}}]},id={174}}, {children={[{id={178}}, {id={179}}, {id={195}}, {id={154}}, {id={157}}]},id={153}}, {children={[{id={181}}, {id={182}}, {id={183}}, {id={189}}]},id={180}}, {id={122}}, {id={21}}, {id={13}}, {id={92}}, {id={22}}, {id={113.... Must be a valid structure or COM object.
In JSON, the [] denotes an array and {} a structure (or object). So your input is actually an array of structures. You need to use an array loop, not a collection loop:
<cfset arrayOfStructs = deserializeJson(output)>
<cfloop array="#arrayOfStructs#" index="parent">
<cfset parentID = parent.id />
...
</cfloop>
children is also an array of structures. Inside the outer loop, check for the existence of that key. If found, loop through the child array and do something with each of the id's:
<cfif structKeyExists(parent, "children")>
<cfloop array="#parent.children#" index="child">
...
</cfloop>
</cfif>
A tidy cfscript version. :)
<cfscript>
structObj = deserializeJson(jsonString);
for(i = 1; i LTE ArrayLen(structObj); i++){
WriteOutput("parent id : " & structObj[i].id & "<br>");
if(StructKeyExists(structObj[i], "children")){
for(j = 1; j LTE ArrayLen(structObj[i].children); j++){
WriteOutput(" -children id : " & structObj[i].children[j].id & "<br>");
}
}
}
</cfscript>
I created an Angular 1.4 ColdFusion 9 JSON Normalizer here
var myURL = 'myCfc.cfc?method=getItemsFromDb';
var app = angular.module('angularOutput',[]);
app.controller("sectionController", function($scope, $http) {
$http.get(myURL).
success(function(data, status, headers, config) {
var log = [];
var output = '';
angular.forEach(data.DATA, function(value, key) {
this.push(output +='{"value": ');
this.push(output += '"'+value[0]+'"');
this.push(output +=',"text":');
this.push(output += '"'+value[1]+'"');
this.push(output +='}');
this.push(output +=',');
}, log);
output = output.replace(/,\s*$/, "");/*had to remove the final comma */
output = '['+output+']'; /*had to add the [] to corectally form the output*/
$scope.sections = angular.fromJson(output);
}).
error(function(data, status, headers, config) {
console.log(data);
});
});

Formatting JSON Data with ColdFusion for HighCharts

So I'm working on a pie chart using HighSlide and ColdFusion.
To make this simple, for the data it expects a string like this:
data: [{name: 'Jane',y: 13}, {name: 'John',y: 23}, {name: 'Joe',y: 19}]
What i've done to accomplish this is to loop through my query results and create a string like this:
<cfloop query="getAreaCounts">
<cfset areaList = listAppend(areaList, "{name: '#name#',y: #y#}")>
</cfloop>
I know there has to be an easier/smarter way right? Since this is JSON data, i figured I could just do this:
<cfoutput>#SerializeJSON(getAreaCounts)#</cfoutput>
But that returns a JSON string like this which highcharts won't process:
{"COLUMNS":["Y","NAME"],"DATA":[[8,"Area1"],[7,"Area2"],[1,"Area3"],[1,"Area4"]]}
Any help pointing me in the right direction would be great. Do I need to dig deeper into a JSON - howto?
You're going to want to convert the query to an array of structs and then run serializeJSON() on that array.
Below is a method that I use pretty frequently when working with a lot of queries and JSON. I think that I got it from Ben Nadel's site and then converted it to cfscript.. I'll try to track down the blog post after I post this answer.
public array function queryToArray( required query qry ) {
var columns = arguments.qry.getColumnNames();
var ofTheJedi = [];
for( var i = 1; i LTE qry.recordCount; i++ ) {
var obj = {};
for( var k = 1; k LTE arrayLen( columns ); k++ ) {
structInsert( obj, columns[ k ], arguments.qry[ columns[ k ] ][ i ] );
}
arrayAppend( ofTheJedi, obj );
}
return ofTheJedi;
}
So, in your case you would do something like this:
<cfset myJSON = queryToArray( getAreaCounts ) />
<cfoutput>#serializeJSON( myJSON )#</cfoutput>
EDIT: Here's Ben's blog post that inspired the method above: http://www.bennadel.com/blog/124-Ask-Ben-Converting-a-Query-to-an-Array.htm
You need something like this (untested but you get the idea)
<cfscript>
data = [{name='Jane',y=13],{name='John',y=23},{name='Joe',y=19}];
</cfscript>
<cfoutput>#serializeJson(data)#</cfoutput>
You need to create a Coldfusion array of strucutres (each with "name" and "y" as members).. then serialize it. What you are serializeing above is the query object. By your code it looks like you meant to serialze the "arealist" variable - but that var would probably not come out correct either because it is not an array of structures - it is a list of strings.