如何将STRUCT - OR - JSON传递给Coldfusion CFC方法

时间:2012-02-28 20:52:01

标签: jquery ajax coldfusion

我有一个现有的CFC,在将结构传递给方法时工作正常。

问题是,我们现在还需要通过JSON将数据传递到同一个函数中。

以下是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 />

以下是我们传递结构的方式:

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

现在,我们还需要传递以下内容,但由于CFC期望结构,显然会出现错误:

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

}

我们如何成功传入getJSON片段?

感谢。

3 个答案:

答案 0 :(得分:3)

JSON只是一个字符串,因此您需要在方法调用到达实际服务层之前“处理”它。

Danimal是正确的,您需要做的是围绕您的服务创建一个Web服务层包装器。

所以你的服务方法如下:

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

您的订阅API如下所示:

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

所以你在订阅API上推送JSON,它将数据转换为结构,并确保你拥有所有正确的数据并将其传递给你的订阅服务。订阅服务中的createSubscription方法检查listid是否存在并检查该人是否已订阅。如果列表良好且订阅不存在,请将新订阅插入数据库,否则返回结果,指示结构中出现问题的API层,将其转换为JSON并返回。

这样做的好处是,您可以重复使用应用程序中的服务,而无需通过API层,并且您的api层处理将请求推送到正确的服务方法并确保有适当的数据可供他们使用。

不要绕过本地范围!在那里可以有大量的东西,包括服务中的所有其他方法。只需返回所需内容即可。

还有其他方法可以解决这个问题,可能更整洁 - 例如,您可以将参数放入JSON的CFC上的方法方法调用中。您可以使用cfajaxproxy在服务和javascript之间创建图层,使您可以直接将您的cfc方法作为javascript函数调用。而且我确信除此之外还有其他解决方案。

记住.... ColdFusion == Serverside,Javascript == clientside。将它们分开。在它们之间放置一层来处理通信。

希望有所帮助。

答案 1 :(得分:2)

如果你想要一个方法来将struct或json字符串作为单个参数,你可以做类似的事情......

<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 :(得分:1)

从原始解决方案编辑:

看起来您不能直接将JSON对象传递给Coldfusion并将其解释为Struct。你可以做的是围绕接受JSON字符串的现有方法创建一个包装器方法,然后将其反序列化为Coldfusion中的结构,以传入现有方法:

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

和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>