2012-03-12 15 views
9

Ho una stringa JSON che analizzo e quindi accedo alle proprietà dell'oggetto con la notazione dot. Tuttavia, nel compilatore di chiusura di google, la notazione a punti (MyObject.PropertyName) avvisa che la proprietà non è definita.compilatore di chiusura di google e json

Per ora, la soluzione che sto utilizzando è quella di convertire il mio codice in notazione parentesi (MyObject['PropertyName']). Questo rimuove l'avviso ma impedisce anche al compilatore di fare il suo lavoro. D'altra parte, quando scrivo JSON.stringify(MyObject), il server riceve una stringa con nomi di proprietà comprensibili.

Quindi la mia domanda è: come utilizzare al meglio il compilatore google in modalità avanzata quando si lavora con oggetti json che sono deserializzati e serializzati in fase di runtime.

risposta

1

Se l'unico codice JavaScript che si sta per scrivere è l'accesso a JSON esterno, quindi sconfigge il punto di utilizzo del compilatore. Tuttavia, se hai anche una piccola quantità di JavaScript che funziona oltre a analizzare il tuo json in modelli di dominio, allora il compilatore può essere utile.

Nel nostro parser accediamo ai nostri dati tramite notazione della parentesi così possiamo ottenere i dati correttamente. Da lì inseriamo i dati nei nostri modelli, che utilizziamo. notazione su Questi vengono ribattezzati selvaggiamente, ci danno il controllo del tipo e tutta quella bontà.

Modifica >> Per i dati, utilizzo lo XHRManager. Questa è una classe seriamente carina. Quando ricevo un evento di dati da quel pool, lo gestisco come segue.

/** 
* @private 
* @param {goog.events.Event} evt The event recieved from the XhrIo. 
*/ 
mypath.MyClass.prototype.onDataRecieved_ = function(evt) { 
    if (evt.type != 'complete') return; 
    var xhrIo = evt.target; 
    var data = xhrIo.getResponseJson(); 
    //do somethign! 
}; 

Devo avvertirvi, la mia gestione XHRManager lascia ancora un bel po 'a desiderare. Ho solo rifattorizzato il mio codice la scorsa settimana per iniziare a usarlo.

Per l'analisi mi fare questo: (Questo è un certo roba grezza dalla mia base di codice, in modo da ignorare alcuni del brutto.)

our.class.path.ContestJsonParser.prototype.setContestProperties = 
    function(contest, element) { 
    contest.setName(element['description']); 
    /** 
    * @type {!number} 
    */ 
    var timeAsInt = element['startTime']; 
    contest.setScheduledStartTime(timeAsInt); 
    var clockModel = contest.getClockModel(); 
    if (goog.isDefAndNotNull(element['period'])) { 
    clockModel.setMatchState(element['period']['periodName']); 
    clockModel.setStateStartTime(element['period']['periodStartTime']); 
    } 
    //TODO (Johan) this needs to change today to consider the rest of the stats 
    //information 
    var stats = element['statistics']; 
    if (goog.isObject(stats) && goog.isDefAndNotNull(stats['score'])) { 
    var score = stats['score']; 
    contest.setMatchScore(score['home'], score['away']); 
    } else { 
    contest.setMatchScore(undefined, undefined); // clears score. 
    } 
}; 
+0

Ti serializzare costantemente i vostri dati tramite JSON.stringify e JSON.parse? questo è estremamente inefficiente, qual è la ragione per cui lo fai. Il mio codice non ha senso per te nel contesto, ma separiamo la creazione del modello dall'analisi utilizzando il modello di build http://en.wikipedia.org/wiki/Builder_pattern. Onestamente penso che il nocciolo del tuo problema potrebbe essere il tuo uso di stringify + parse, spiegami cosa stai cercando di risolvere con questo. – lennel

+0

Sì, uso il serializzatore nativo. Qual è l'opzione migliore? Ho letto da qualche parte che usare una libreria è più lento rispetto all'utilizzo di un'analisi nativa. Gli oggetti vanno e vengono via ajax e anche da e verso la memoria locale. – frenchie

+0

Ho appena modificato il mio commento, ricontrollare e spiegarmi perché usi Json.stringify e Json.parse per tutto il tempo. – lennel

5

Che, fondamentalmente, hanno due scelte:

  1. uso degli oggetti accesso dell'array usando la stringa letterale (ovvero MyJsonObject['PropertyName']) questa è la soluzione più semplice.
  2. creare un file esterno che descriva le proprietà nell'oggetto JSON e quindi utilizzare la notazione dot (ovvero MyJsonObject.PropertyName). Ciò richiede più manutenzione ma consente al compilatore di digitare controllare le proprietà se si forniscono annotazioni di tipo nella descrizione esterna.
+0

Hai qualche risorsa che posso guardare per specificare i file extern? Grazie! –

+1

https://developers.google.com/closure/compiler/docs/api-tutorial3?hl = it # externs In generale, gli extern devono essere javascript validi, ma dichiarazioni semplificate: var – John

1

EDIT: la direttiva @expose è stato deprecato


Google Closure Compiler consente di specificare le direttive sulle modalità di compilazione deve essere fatto attraverso le annotazioni .

See: https://developers.google.com/closure/compiler/docs/js-for-compiler

correttamente utilizzando @expose e @type è possibile conservare il nome di una proprietà nel codice.

È possibile decodificare in modo sicuro una stringa JSON in un oggetto e accedere a tale oggetto utilizzando la notazione punto. Potrai anche specificare per restringere i dati.

-

Facciamo un esempio:

Si desidera analizzare un array di oggetti. Ogni oggetto rappresenta una "dimensione" , con le proprietà w per la larghezza e h per l'altezza.

Dichiarare un prototipo per la dimensione oggetto e espongono sue proprietà w e h

function size() {} 

/** @expose */ 
size.prototype.w = 0; 
/** @expose */ 
size.prototype.h = 0; 

poi si vuole mettere il JSON analizzato i dati in un array chiamato dati.

Utilizzando @type si dichiara che i dati sta per tenere un serie di oggetto di tipo dimensioni.

function main() 
{ 
    /** @type {Array.<size>} */ 
    var data; 

    // string built up just for example purposes 
    var response = '[{"w": 10, "h": 20}]'; 

    // parse the array 
    var data = JSON.parse(response); 

    // access data with dot notation! 
    console.log(data[0].w+ " "+ data[0].h); 
} 

main(); 
+0

Non riesco a trovare alcuna menzione di "@ expose" sulla pagina Web a cui si punta. Questa annotazione è documentata da qualche parte? – jochen

+0

@jochen la direttiva '@ expose' è stata rimossa dalla documentazione. Sorprendentemente non è nemmeno menzionato come deprecato. Sembra che '@ expose' appaia solo su alcune risposte SO, come le mie. Suppongo che sia ancora supportato per evitare di rompere il codice legacy ma non ho controllato. Sto ancora usando una vecchia versione del Closure Compiler (da tempo '@ expose' è stata documentata e implementata) – Paolo

+0

' @ expose' è ora ufficialmente deprecato. –

Problemi correlati