2011-09-27 10 views
6

Ho un CFC remoto che restituisce una struttura. Si chiama usando cfajaxproxy. Voglio che il JSON sia tornato in ordine per prima cosa nella struttura prima nell'oggetto JSON. Tuttavia, il JSON restituito è in ordine misto.JSON restituito dalla funzione CFC remota è fuori servizio

Ecco la funzione remota.

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

Questo è il cfajaxproxy che ho impostato nella parte superiore della pagina del modulo.

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

Ecco la chiamata effettuata alla funzione remota nel gestore onSubmit del mio modulo.

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

Ecco i dati (o variabile sopra) che vengono inviati alla funzione nella richiesta di post.

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

Ecco la risposta JSON restituita dalla funzione.

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

Voglio che la risposta sia nello stesso ordine in cui è stata creata la struttura che apparirebbe così.

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

In questo modo quando ho iterare la risposta che posso impostare la messa a fuoco per il primo campo modulo con un errore in esso.

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

In questo momento questi luoghi si concentrano nel secondo campo della forma, descrizione, invece che nel campo del progetto.

+0

Possibile duplicato di http://stackoverflow.com/questions/4515676/keep-the-order-of-the-json-keys-during-json-conversion-to-csv –

risposta

7

Le chiavi di una struttura ColdFusion non vengono mai memorizzate in un ordine particolare. Tuttavia, I found one post mostra come è possibile creare una Java LinkedHashMap (che è la java sotto una CF Struct) per archiviare e recuperare le chiavi in ​​un ordine specifico.

<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: soluzione di Dan (array anziché struct) probabilmente sarebbe molto più facile.

+0

Se stavo usando la funzione di convalida remota tramite chiamate ajax, probabilmente sarei andato con l'approccio di Dan e ho restituito gli errori in un array. Tuttavia, chiamo anche la funzione sul server nel caso in cui abbiano disabilitato JS. Restituire gli errori in una struttura anziché in un array funziona meglio con il mio codice di visualizzazione degli errori. L'utilizzo di LinkedHashMap ha risolto il problema; il JSON restituito era nello stesso ordine in cui erano stati aggiunti gli articoli. – Brandon

5

Non è possibile (facilmente) controllare l'ordine dei dati di struttura JSON restituiti a meno che non si costruisca manualmente la stringa per restituire tali dati. Se è necessario affidarsi a un ordine, è necessario restituire gli errori in una matrice anziché in una struttura. È anche possibile restituire una matrice di strutture di errore e CF manterrà l'ordine di array corretto.

Vorrei restituire i dati in questo modo:

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

Questo darebbe un array separato di errori di ciclo finito, invece di trattare con la vostra base message e areErrors chiavi allo stesso tempo come i vostri errori. Sconfiggili completamente in un'entità separata, e avrai un momento più semplice per eseguirne il looping dal lato client.

+0

Questo suona come l'approccio corretto. Lo proverò. – Brandon

+0

Fammi sapere se hai qualche problema. Ho digitato il codice direttamente nella risposta e in realtà non l'ho eseguito per testarlo. Tuttavia, tutto dovrebbe essere buono per andare. –

+0

C'è un problema che ho trovato con il tuo codice. La struttura tempError viene aggiunta all'array solo una volta e continua a essere sovrascritta in modo che nell'array degli errori venga visualizzato solo l'ultimo errore. Lo spostamento di tempError = StructNew() all'interno di ogni blocco cfif risolve questo problema. – Brandon

3

struct non è ordinato in CFML (è solo una raccolta di tipo Hashmap).

se si vuole ordinato struct, utilizzare

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

Il modo più semplice se si vuole qualcosa di rimanere al fine di utilizzare un array invece di una struttura.

Problemi correlati