How to get STRUCT - OR - JSON in the ColdFusion CFC Method

I have an existing CFC that works great when passing structures to a method.

The problem is that we also need to pass the data to the same function via JSON.

Here is a snippet of CFC:

<cffunction name="subscribeAPI" access="remote" returntype="struct" returnformat="json" output="false"> <cfargument name="structure" type="struct" required="true" hint="data structure received from call"> <cfif StructKeyExists(arguments.structure, "listID") AND len(arguments.structure.listID)> ... </cfif> <cfreturn LOCAL /> 

Here's how we go in structure:

 <cfset preStruct = { apiAction="Create", listID="1463", email="#form.cartEmail#", firstname="#form.first_name#", preCart="#now()#", planDescription="#application.name.site#" } /> <cfscript>voidReturn = application.goxObj.subscribeAPI(preStruct);</cfscript> 

Now we also need to pass the following, but, obviously, get errors due to the fact that the CFC expects a structure:

 function HandleSubscribe(){ $j.getJSON( "/com/list.cfc?wsdl", { method : "subscribeAPI", action : "Create", listID : $j( "#listID" ).val(), triggerKey : $j( "#triggerKey" ).val(), email : $j( "#emailNL" ).val(), firstname : $j( "#firstnameNL" ).val() }, handleSubscribeCallback ); 

}

How can we successfully pass the getJSON fragment?

Thanks.

+6
source share
3 answers

JSON is just a string, so you need to β€œprocess” the method call before it reaches your actual level of service.

Daniel is right in that you need to create a web service-level wrapper around your service.

So, your service method is as follows:

 <cffunction name="CreateSubscription" access="public" returntype="struct" output="false"> <cfargument name="listID" required="true" type="numeric"> <cfargument name="emailaddress" required="true" type="string"> <cfargument name="firstname" required="true" type="string"> <cfset var resultset = {success=false}> <!--- Validate your listid and subscription details ---> <!--- If Valid Then insert subscription ---> <cfset resultset.success = true> <!--- else ---> <cfset resultset.message = 'kerboom!'> <!--- only return what you need as a struct, not the whole local scope! ---> <cfreturn resultset /> </cffunction> 

Your subscription API is as follows:

 <cffunction name="subscribeAPI" access="remote" returntype="struct" returnformat="json" output="false"> <cfargument name="JSONPacket" type="string" required="true" hint="data structure received from call"> <cfset var incomingData = deserializeJSON(arguments.JSONPacket)> <cfset var resultset = {success=false,message='invalid data'}> <cfif StructKeyExists(incomingData, "apiAction")> <cfif incomingData.apiAction EQ "create"> <!--- You should also check you have the required fields for the createSubscription method here too. ---> <cfset resultset = subscriptionService.createSubscription(incomingData)> </cfif> <cfelse> <cfset resultset.message = 'No API Action specified'> </cfif> <cfreturn resultset> </cffunction> 

Thus, you click JSON on the subscription API, which converts the data into a structure and ensures that you have all the data you need and is passed to the subscription service. The createSubscription method in the subscription service checks to see if listid exists and checks to see if the person is signed. If the list is good and the subscription does not exist, insert the new subscription into the database, otherwise return the results that indicate what went wrong in the structure to your API level, which converts it to JSON and returns it.

The advantage of this is that you can reuse services in your application without going through the API level, and your api level processes requests for the correct service methods and makes sure that the appropriate data is available to them,

Do not skip the local area around! There may be a load on things, including all other methods in the service. Just return what is required and nothing else.

There are other ways to solve this problem that may be more accurate - for example, you can actually argue the method of calling a method on CFC from JSON. You can use cfajaxproxy to create a layer between your service and your javascript, allowing you to directly call your cfc methods as javascript functions. And I'm sure there are other solutions.

Remember ... ColdFusion == Serverside, Javascript == clientside. Separate them. Place a layer between them to handle messages.

Hope this helps.

+3
source

If you want the method to accept either a string or a json string as a single argument, you can do something like ...

 <cffunction name="myFunction" access="remote" returntype="Struct" returnformat="JSON"> <cfargument name="data" type="any" required="true"> <cfif isJson(arguments.data)> <cfset arguments.data = deserializeJSON(arguments.data) /> </cfif> <cfif NOT isStruct(arguments.data)> <cfthrow message="argument must be structure or a json string" /> </cfif> ... </cffunction> 
+2
source

Edited from the original solution:

It doesn't look like you can pass the JSON object directly to Coldfusion and interpret it as Struct. What you can do is create a wrapper method around an existing method that accepts a JSON string and then deserializes it into a Coldfusion structure to go to the existing method:

 <script> var data = { dude: "wow"}; $(function() { $('#ajax').click(function() { $.getJSON( "test.cfc", { method: "foo", json: JSON.stringify(data) }, function(data) { // so something with result } ); }); }) </script> 

And Coldfusion:

 <cffunction name="foo" access="remote" returntype="Struct" returnformat="JSON"> <cfargument name="json" type="string" /> <cfset myStruct = DeserializeJSON(arguments.json) /> <!--- now call your existing method passing it myStruct ---> </cffunction> 
+1
source

Source: https://habr.com/ru/post/909579/


All Articles