从远程CFC函数返回的JSON出错

Bra*_*don 6 coldfusion jquery json cfc

我有一个返回结构的远程CFC.它使用cfajaxproxy调用.我希望返回的JSON按顺序排列,即首先进入JSON对象的结构.但是,返回的JSON是混合顺序.

这是远程功能.

<cfcomponent displayname="validation" hint="">
    <cffunction name="validateForm" displayname="validateForm" hint="" access="remote" verifyClient="yes" returntype="struct">

        <cfargument name="formVals" type="struct" required="yes">

        <cfset errors = StructNew()>

        <cfif formVals.project neq "project">
              <cfset errors["project"] = "Invalid project name." />
        </cfif>

        <cfif Len(formVals.description) eq 0>
             <cfset errors["description"] = "Please enter a description." />
        </cfif>

        <cfif StructIsEmpty(errors)>
            <cfset errors["message"]["type"] = "success">
            <cfset errors["message"]["text"] = "Client and server-side validation passed successfully.">
            <cfset errors["areErrors"] = false>
        <cfelse>
            <cfset errors["message"]["type"] = "validation">
            <cfset errors["message"]["text"] = "Please fix the errors, and resubmit.">
            <cfset errors["areErrors"] = true>
        </cfif>

        <cfreturn errors />

    </cffunction>
</cfcomponent>
Run Code Online (Sandbox Code Playgroud)

这是我在表单页面顶部设置的cfajaxproxy.

<cfajaxproxy cfc="validation" jsclassname="validation">
Run Code Online (Sandbox Code Playgroud)

这是在我的表单的onSubmit处理程序中对远程函数的调用.

var v = new validation();
v.setHTTPMethod("POST");
var errors = v.validateForm(o);
Run Code Online (Sandbox Code Playgroud)

这是发布请求中发送给函数的数据(上面的o变量).

{"formVals":{"project":"","description":""}}
Run Code Online (Sandbox Code Playgroud)

这是从函数返回的JSON响应.

{"message":{"text":"Please fix the errors, and resubmit.","type":"validation"},"description":"Please enter a description.","project":"Invalid project name.","areErrors":true}
Run Code Online (Sandbox Code Playgroud)

我希望响应的顺序与创建的结构的顺序相同.

{"project":"Invalid project name.","description":"Please enter a description.","message":{"text":"Please fix the errors, and resubmit.","type":"validation"},"areErrors":true}
Run Code Online (Sandbox Code Playgroud)

这样,当我迭代响应时,我可以将焦点设置为第一个表单字段,其中包含错误.

var focusSet = false;

$.each(errors, function(key, val){
    //alert(key + ': ' + val);
    if(key != 'message' && key != 'areErrors') {
        var fi = $('#' + key).parents('.formItem').filter(':first');
        fi.addClass("inError");
        fi.find('.err').filter(':first').html(val);
        if(!focusSet) {
            $('#' + key).focus();
            focusSet = true;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

现在,这将焦点放在表单的第二个字段中,而不是在项目字段中.

Adr*_*eno 7

ColdFusion结构的键永远不会以任何特定顺序存储.但是,我发现了一篇文章,展示了如何创建一个java LinkedHashMap(它是CF Struct下面的java)来按特定顺序存储和检索密钥.

<cfset pets = CreateObject("java", "java.util.LinkedHashMap").init()>
<cfscript>
pets["Cat Name"] = "Leo";
pets["Dog Name"] = "Meatball";
pets["Fish Name"] = "Lil Fish";
pets["Bird Name"] = "PePe";
pets["Snake Name"] = "Sizzle";
</cfscript>
<cfloop collection="#pets#" item="key" >
    <cfoutput>
    #key#: #pets[key]#<br/>
    </cfoutput>
</cfloop>
Run Code Online (Sandbox Code Playgroud)

编辑: Dan的解决方案(数组而不是struct)可能会更容易.


Dan*_*ort 5

您不能(轻松)控制返回的JSON结构数据的顺序,除非您手动构建字符串以返回该数据.如果您必须依赖订单,那么您需要在数组而不是结构中返回错误.您甚至可以返回一组错误结构,CF将保持正确的数组顺序.

我会像这样返回你的数据:

<cfcomponent displayname="validation" hint="">
    <cffunction name="validateForm" displayname="validateForm" hint="" access="remote" verifyClient="yes" returntype="struct">

        <cfargument name="formVals" type="struct" required="yes">

        <cfset var retVal = StructNew() />
        <cfset var tempError = StructNew() />
        <cfset retVal.errors = ArrayNew(1) />

        <cfif formVals.project neq "project">
            <cfset tempError["key"] = "project" />
            <cfset tempError["message"] = "Invalid project name." />
            <cfset ArrayAppend(retVal.errors, Duplicate(tempError)) />
        </cfif>

        <cfif Len(formVals.description) eq 0>
            <cfset tempError["key"] = "description" />
            <cfset tempError["message"] = "Please enter a description." />
            <cfset ArrayAppend(retVal.errors, Duplicate(tempError)) />
        </cfif>

        <cfif ArrayIsEmpty(retVal.Errors)>
            <cfset retVal["message"]["type"] = "success" />
            <cfset retVal["message"]["text"] = "Client and server-side validation passed successfully.">
            <cfset retVal["areErrors"] = false>
        <cfelse>
            <cfset retVal["message"]["type"] = "validation">
            <cfset retVal["message"]["text"] = "Please fix the errors, and resubmit.">
            <cfset retVal["areErrors"] = true>
        </cfif>

        <cfreturn retVal />

    </cffunction>
</cfcomponent>
Run Code Online (Sandbox Code Playgroud)

这会给你一个单独的错误数组来循环,而不是在你的错误的同时处理你的基础messageareErrors键.将它们分解为一个单独的实体,您将在客户端更容易地循环它们.