4

I have a cfc that creates an output string containing JSON. The payload is fine but the person receiving it tells me that the data is coming in as text/html and his program doesn't recognize it as valid because it needs to be application/json.

So I modified the parameters in my CFFUNCTION statement and I have built a small test program that says:

 <cffunction name="Test" httpmethod="get" returntype="JSON" output="yes" access="remote">
    <cfset JSON='{"Test": "A"}'>
    <cfreturn JSON>
    </cffunction>

But when I execute this cfc remotely, I get the error message "The value returned from the Test function is not of type JSON".

This should be easy but I can't see what I need to do to return a JSON string with the application/json type.

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
John P
  • 87
  • 7
  • 1
    `serializeJSON` is designed to convert ColdFusion data to a JSON. ColdFusion data does include string variables so maybe that's the path to take. Here is a reference of that function: https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-s/serializejson.html – Dan Bracuk Mar 04 '21 at 04:21
  • I noticed the function uses `httpmethod`. If this is a RESTful web service, did you try using the `produces` attribute? – SOS Mar 05 '21 at 16:27
  • 1
    I was just grasping for ideas at the point that I added the httpmethod. Fortunately returning to my original parameters and adding the CFHeader worked. – John P Mar 06 '21 at 18:13

1 Answers1

5

Your first issue will be that returntype="JSON" - it looks like you're confusing returntype and returnformat. There are various ways of achieving what you're trying to do, eg each of these would return the same result:

<!--- Function returns a struct, ask CF to convert it to JSON using returnformat: --->
<cffunction name="Test2" returntype="struct" returnformat="JSON" output="false" access="remote">
    <cfset var myStruct={"Test"="A", "foo"="bar"} />
    <cfreturn myStruct />
</cffunction>

<!--- Function uses a struct, but serializes as a JSON string before returning --->
<cffunction name="Test3" returntype="string" returnformat="plain" output="false" access="remote">
    <cfset var myStruct={"Test"="A", "foo"="bar"} />
    <cfreturn SerializeJSON(myStruct)>
</cffunction>

<!--- Same as above but another variation of struct notation. 
    Note that most CF environments will convert unquoted key names to uppercase 
    unless you enable serialization.preserveCaseForStructKey at application or CF Admin level --->
<cffunction name="Test4" returntype="string" returnformat="plain" output="false" access="remote">
    <cfset var myStruct=structNew() />
    <cfset myStruct['Test'] = "A" />
    <cfset myStruct['foo'] = "bar" />
    <cfreturn SerializeJSON(myStruct) />
</cffunction>

<!--- Manually build the JSON string yourself from scratch, beware of encoding/escaping issues --->
<cffunction name="Test5" returntype="string" returnformat="plain" output="false" access="remote">
    <cfset var myJSONString='{"Test":"A","foo":"bar"}' />
    <cfreturn myJSONString />
</cffunction>

Note that the above alone will not set the content type response header to application/json, if your caller actually cares about that, then you'll need something like: <cfheader name="Content-Type" value="application/json; charset=utf-8" /> ...but the The value returned from the Test function is not of type JSON error you refer to is a CF runtime error, not a browser/ajax error. The full text of that error would normally be:

The value returned from the Test function is not of type JSON. If the component name is specified as a return type, it is possible that either a definition file for the component cannot be found or is not accessible.

Sev Roberts
  • 1,295
  • 6
  • 7
  • The caller is a 3rd party software package (Golf Genius) and the tech staff tell me that the type I respond with must be application/json. My original code was pretty much like you have in the final example and it looked good to me. I can insert that cfheader statement and give it a try, but do I just plug that in, right in front of the cfreturn? – John P Mar 04 '21 at 18:13
  • 1
    I plugged that cfheader right before the cfreturn and that seems to have solved the problem. Thanx a lot. – John P Mar 04 '21 at 20:18