2013-07-02 27 views
7

L'adattatore REST Ember.js aspetta il JSON da restituire come:Ember.js REST adattatore senza radice JSON

{ 
    "person": { 
     "first_name": "Barack", 
     "last_name": "Obama", 
     "is_person_of_the_year": true 
    } 
} 

Ma il mio API restituisce i dati senza un elemento radice:

{ 
    "first_name": "Barack", 
    "last_name": "Obama", 
    "is_person_of_the_year": true 
} 

È possibile personalizzare l'adattatore REST in modo che accetti i miei dati JSON? In questo momento sta mostrando "Asserzione fallita: Il server ha restituito un hash con il tasto 0, ma non si ha la mappatura per esso"

UPDATE: in base alla risposta del Sherwin Yu sotto, questo è ciò che mi si avvicinò con , sembra funzionare finora: https://gist.github.com/richardkall/5910875

risposta

8

Sì, è possibile scrivere il proprio adattatore REST personalizzato. Dai uno sguardo al codice sorgente nel JSONSerializer, RESTSerializer (che estende JSONSerializer) e allo REST adapter.

Fondamentalmente, è necessario sovrascrivere i metodi extract* da JSONSerializer.

Attualmente, sembra qualcosa di simile:

extract: function(loader, json, type, record) { 
    var root = this.rootForType(type); 

    this.sideload(loader, type, json, root); 
    this.extractMeta(loader, type, json); 

    if (json[root]) { 
    if (record) { loader.updateId(record, json[root]); } 
    this.extractRecordRepresentation(loader, type, json[root]); 
    } 
}, 

Notate come esso controlla json[root] - che avrebbe dovuto scrivere il vostro metodo personalizzato in base alla tua risposta API previsto.

Un altro approccio sarebbe quello di "pre-elaborare" il json dall'API per utilizzare un elemento radice. Si può fare questo scoprendo quali metodi chiamano extract* (che gli passa il json) e prima di farlo, modificare il json per contenere l'elemento root.

Spero che questo aiuti, per favore fatemi sapere se non è chiaro.

+0

risposta Nizza. Grazie! –

+0

Fantastico! Grazie mille! Questo sembra funzionare: https://gist.github.com/richardkall/5910875 – Richard

-1

Ho cercato di aggiungere root a json. Questo funziona per me:

App.Adapter = DS.RESTAdapter.extend({ 
    findAll: function(store, type, since) { 
     var root, adapter; 
      var plural; // Insert this line 
     root = this.rootForType(type); 
     adapter = this; 
      plural = this.pluralize(root); // Insert this line 
     return this.ajax(
       this.buildURL(root), 
       "GET", 
       { 
        data: this.sinceQuery(since) 
       }).then(function(json) { 
        eval ("json = {" + plural + " : json }"); // Insert this line 
        adapter.didFindAll(store, type, json); 
       }).then(null, DS.rejectionHandler); 
    } 
}); 
+4

Manipolare la risposta appartiene a un serializzatore, non a un adattatore. –

15

Si potrebbe anche normalizzarlo in qualcosa che il burbero si aspetterebbe.

App.PersonSerializer = DS.RESTSerializer.extend({ 
    normalizePayload: function(type, payload) { 
    var typeKey = type.typeKey; 
    return { 
     typeKey: payload 
    } 
    } 
}); 
+1

'type' non è più disponibile, solo' payload'. http://emberjs.com/api/data/classes/DS.RESTSerializer.html # method_normalizePayload – rog

+0

Questa è la strada da percorrere, rispetto alla risposta accettata in quanto lo sviluppatore non deve preoccuparsi del tipo di payload (Array, Single object) e non deve preoccuparsi di operazioni di archivio. – kiddouk

+0

Questa è l'idea giusta, ma il codice non funziona. La chiave del valore di ritorno è letteralmente "tipoKey", non il valore memorizzato da 'var typeKey'. – Andrew

1

Ho risolto questo estendendo DS.RESTSerializer. Il metodo extractArray deve essere sovraccaricato quando la risposta del server è di tipo array.

App.PersonSerializer = DS.RESTSerializer.extend({ 
    extractSingle: function (store, type, payload, id) { 
     var wrappedObj = {}; 
     wrappedObj[type.typeKey] = payload; 
     return this._super(store, type, wrappedObj, id); 
    }}); 
Problemi correlati