For reasons beyond my control, I need to manually create a JSON structure to post to an API. I've done so as follows;
<cfsavecontent variable="JSONData">
{"data":[{"Last_Name":"#lastname#",
"First_Name":"#firstname#",
"$gclid":"#zc_gad#",
"Email":"#email#",
"Phone":"#phonenumber#",
"Lead_Source":"PPC",
"Build_Cost_text":"#buildcost#",
"Estimated_Sales_Value_text":"#estsalesvalue#",
"Stage_of_Build_Work":"#stageofbuildingwork#",
"Work_Starting_Date_text":"#workstartdate#",
"No_Of_Units_text":"#numofunits#",
"Address_of_Development":"#devaddress#",
"Do_you_require_a_quote_for_building_control1":"#bcquote#",
"Gross_Floor_Area_text":"#grossfloorarea#",
"Development_Use":"#devuse#",
"Please_share_any_additional_information":"#additionalinfo#",
"Product_Type":"Warranty","Company":"#company#"}]}
</cfsavecontent>
(The actual code doesn't have linebreaks - it's just a bit harder to read!)
I then use that to post to the API;
<cfhttp method="POST" url="APIurl" result="postresult">
<cfhttpparam type="header" name="Authorization" value="oauthtokenvalue">
<cfhttpparam type="header" name="content-type" value="application/json" />
<cfhttpparam type="body" value="#JSONData#" />
</cfhttp>
If, instead of populating it with dynamic values, eg "#lastname#" is hardcoded as "Smith", it works just fine.
However, as soon as I add the dynamic tags, I get the following error;
Can't cast Complex Object Type Struct to String
Changing the cfhttpparam (for the sake of testing) to;
<cfhttpparam type="body" value="#SerializeJSON(JSONData)#" />
Makes no difference either.
If it matters, above this is the cfquery that retrieves the record(s), then this is wrapped in a cfoutput query - and aside from the dynamic references, that's the only difference between the 'working' code and non-working code.
SaveContent saves whatever you are outputting to a string. The code you are showing may not be outputting anything. Instead, it's possible that you are creating a struct. To make sure you are outputting the JSON, add a tag as follows:
<cfsavecontent variable="JSONData">
<cfoutput>
{"data":[{"Last_Name":"#lastname#",
"First_Name":"#firstname#",
...
}]
}
</cfoutput>
</cfsavecontent>
But, a better way to do this would be to use SerializeJSON(). I can't think of a reason why you wouldn't be able use it. For example:
<cfscript>
myQuery = queryExecute(...);
myData = {
"data": []
}
for (record in myQuery) {
arrayAppend(myData.data, {
"last_Name": record.lastName,
"First_Name": record.firstName
...
});
}
WriteOutput(SerializeJSON(myData));
</cfscript>
Either way, you need to view your string to debug, which should give you a better idea of what the problem is. I would add a <cfdump var="#jsonData#">
after you've created your string to see what it looks like. You could also output <pre>#EncodeForHTML(jsonData)#</pre>
or <pre>#HTMLEditFormat(jsonData)#</pre>
to see it.
But the bigger question is why you need to build the json manually. I know you say it's for reasons beyond your control. Perhaps you're using an old version of ColdFusion?? It doesn't matter what version of CFML you're using, you should still be able to loop over a query and append a struct of the record's values to an array, and then output them using SerializeJSON(). If your issue is an old version of SerializeJSON() that is buggy, there are UDFs out there that work around some of the old problems with SerializeJSON(), or you could write your own that would be better than building a string.