2011-09-27 11 views
6

구조체를 반환하는 원격 CFC가 있습니다. cfajaxproxy를 사용하여 호출됩니다. JSON 객체가 처음으로 구조체에 들어오는 JSON을 순서대로 정렬해야합니다. 그러나 반환 된 JSON은 혼란스러운 순서로 존재합니다.원격 CFC 함수에서 반환 된 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> 

이것은 내 양식 페이지 맨 위에 설정 한 cfajaxproxy입니다.

<cfajaxproxy cfc="validation" jsclassname="validation"> 

다음은 내 양식의 onSubmit 처리기에서 원격 기능에 대한 호출입니다.

var v = new validation(); 
v.setHTTPMethod("POST"); 
var errors = v.validateForm(o); 

게시 요청의 함수로 전송되는 데이터입니다 (위 변수는 위 참조).

{"formVals":{"project":"","description":""}} 

다음은 함수에서 반환 된 JSON 응답입니다.

{"message":{"text":"Please fix the errors, and resubmit.","type":"validation"},"description":"Please enter a description.","project":"Invalid project name.","areErrors":true} 

구조가 생성 된 것과 같은 순서로 응답을 보내고 싶습니다.

{"project":"Invalid project name.","description":"Please enter a description.","message":{"text":"Please fix the errors, and resubmit.","type":"validation"},"areErrors":true} 

그런 식으로 응답을 반복 할 때 오류가있는 첫 번째 양식 필드에 포커스를 설정할 수 있습니다.

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

지금은 프로젝트 필드 대신 설명의 두 번째 필드에 초점을 맞 춥니 다.

+0

가능한 복제 http://stackoverflow.com/questions/4515676/keep-the-order-of-the-json-keys-during-json-conversion-to-csv –

답변

7

ColdFusion 구조체의 키는 특정 순서로 저장되지 않습니다. 그러나 특정 순서로 키를 저장하고 검색하는 Java LinkedHashMap (CF Struct 아래의 java)을 만드는 방법을 보여주는 found one post입니다.

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

편집 : 댄의 솔루션 (대신 구조체의 배열) 아마 훨씬 쉬울 것이다.

+0

ajax 호출을 통해서만 원격 유효성 검사 기능을 사용했다면 아마도 Dan의 접근법을 따라 가고 배열의 오류를 반환했을 것입니다. 그러나 JS가 비활성화 된 경우 서버의 함수를 호출합니다. 배열이 아닌 구조에서 오류를 반환하면 오류 표시 코드가 더 잘 작동합니다. LinkedHashMap을 사용하면 문제가 해결됩니다. 반환 된 JSON은 항목이 추가 된 순서와 같습니다. – Brandon

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> 

이 대신 기지 message하고 오류와 동시에 areErrors 키를 다루는, 돌이 당신에게 오류 별도의 배열을 줄 것이다. 그들을 분리 된 엔티티로 완전히 분리하면 클라이언트 측에서 루프를 반복하는 것이 더 쉬워집니다.

+0

올바른 접근 방식처럼 들립니다. 나는 그것을 시도 할 것이다. – Brandon

+0

당신이 어떤 장애를 치면 알려주세요. 필자는 코드를 직접 대답에 입력하고 테스트를 위해 실제로 실행하지 않았습니다. 그러나 모든 것이 잘되어야합니다. –

+0

코드에 문제가 하나 있습니다. tempError 구조체는 배열에 한 번만 추가되고 마지막 배열 만 오류 배열에 나타나도록 계속 덮어 씁니다. 각 cfif 블록 내부에서 tempError = StructNew()를 이동하면이 문제가 해결됩니다. – Brandon

3

구조체가 CFML에서 정렬되지 않습니다 (단지 Hashmap과 유사한 콜렉션 임).당신이 구조체를 주문하려는 경우 구조 대신 배열을 사용하는 일이 순서를 유지하려면

,

struct function orderedStructNew() 
{ 
    return createObject("java","java.util.LinkedHashMap").init(); 
} 
2

가장 쉬운 방법을 사용합니다.

관련 문제