2011-09-27 13 views
6

Tôi có một CFC từ xa trả về cấu trúc. Nó được gọi là sử dụng cfajaxproxy. Tôi muốn JSON được trả về theo thứ tự, tức là đầu tiên vào cấu trúc đầu tiên vào đối tượng JSON. Tuy nhiên, JSON được trả về là theo thứ tự hỗn hợp.JSON được trả lại từ chức năng CFC từ xa đã hết trật tự

Đây là chức năng từ xa.

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

Đây là cfajaxproxy mà tôi đã đặt ở đầu trang biểu mẫu của tôi.

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

Đây là cuộc gọi được thực hiện với chức năng từ xa trong trình xử lý onSubmit của biểu mẫu của tôi.

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

Đây là dữ liệu (o biến ở trên) được gửi đến hàm trong yêu cầu bài đăng.

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

Đây là phản hồi JSON được trả về từ hàm.

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

Tôi muốn phản hồi theo thứ tự như cấu trúc được tạo trông giống như thế này.

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

Bằng cách đó khi tôi lặp lại phản hồi, tôi có thể đặt trọng tâm vào trường biểu mẫu đầu tiên có lỗi trong đó.

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

Hiện tại, địa điểm này tập trung vào trường thứ hai của biểu mẫu, mô tả, thay vì trong trường dự án.

+0

Bản sao có thể có của http://stackoverflow.com/questions/4515676/keep-the-order-of-the-json-keys-during-json-conversion-to-csv –

Trả lời

7

Các khóa của cấu trúc ColdFusion không bao giờ được lưu trữ theo bất kỳ thứ tự cụ thể nào. Tuy nhiên, tôi found one post cho thấy cách bạn có thể tạo một LinkedHashMap java (là java bên dưới CF Struct) để lưu trữ và truy xuất các khóa theo thứ tự cụ thể.

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

EDIT: giải pháp của Dan (mảng thay vì struct) có lẽ sẽ dễ dàng hơn nhiều.

+0

Nếu tôi chỉ sử dụng chức năng xác nhận từ xa thông qua các cuộc gọi ajax, tôi có thể đã đi với phương pháp của Dan và trả về các lỗi trong một mảng. Tuy nhiên, tôi cũng gọi hàm trên máy chủ trong trường hợp họ đã tắt JS. Trả lại các lỗi trong một cấu trúc chứ không phải là một mảng hoạt động tốt hơn với mã hiển thị lỗi của tôi. Sử dụng LinkedHashMap đã giải quyết được vấn đề; JSON được trả lại theo thứ tự giống như các mục đã được thêm vào. – Brandon

5

Bạn không thể (dễ dàng) kiểm soát thứ tự dữ liệu cấu trúc JSON được trả về trừ khi bạn xây dựng chuỗi theo cách thủ công để trả về dữ liệu đó. Nếu bạn phải dựa vào một đơn đặt hàng, thì bạn cần trả về các lỗi của bạn trong một mảng thay vì một cấu trúc. Bạn thậm chí có thể trả về một mảng các cấu trúc lỗi và CF sẽ duy trì thứ tự mảng chính xác.

tôi sẽ trả lại dữ liệu của bạn như vậy:

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

Điều này sẽ cung cấp cho bạn một mảng riêng biệt của lỗi để lặp kết thúc, thay vì đối phó với cơ sở của bạn messageareErrors phím cùng lúc như lỗi của bạn. Chia chúng thành một thực thể riêng biệt hoàn toàn, và bạn sẽ có một thời gian dễ dàng hơn để lặp qua chúng ở phía khách hàng.

+0

Điều này nghe giống như cách tiếp cận chính xác. Tôi sẽ thử nó. – Brandon

+0

Hãy cho tôi biết nếu bạn nhấn bất kỳ snags nào. Tôi gõ mã lên trực tiếp trong câu trả lời, và không thực sự chạy nó để kiểm tra nó. Tuy nhiên, tất cả mọi thứ nên được tốt để đi. –

+0

Có một vấn đề tôi tìm thấy với mã của bạn. Cấu trúc tempError chỉ được thêm vào mảng một lần và tiếp tục bị ghi đè để chỉ lỗi cuối cùng xuất hiện trong mảng lỗi. Di chuyển tempError = StructNew() bên trong mỗi khối cfif sửa lỗi này. – Brandon

3

struct không được đặt hàng trong CFML (nó chỉ là một bộ sưu tập giống như Hashmap).

Nếu bạn muốn ra lệnh struct, sử dụng

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

Cách đơn giản nhất nếu bạn muốn một cái gì đó để giữ trật tự sử dụng một mảng thay vì một cấu trúc.