2013-07-02 13 views
7

ember.js REST Adapter oczekuje JSON zostać zwrócone jako:ember.js REST JSON Adapter bez korzenia

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

Ale mój API zwraca dane bez elementu głównego:

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

Czy można dostosować adapter REST tak, aby akceptował moje dane JSON? Teraz to pokazuje „Assertion failed: Twój serwer zwrócił skrótu z kluczem 0, ale nie masz mapowanie to

UPDATE: podstawie odpowiedzi Sherwin Yu poniżej, to co wymyśliłem , wydaje się działać do tej pory: https://gist.github.com/richardkall/5910875

Odpowiedz

8

Tak, możesz napisać własną niestandardową kartę REST. Spójrz na kod źródłowy w JSONSerializer, RESTSerializer (który rozszerza JSONSerializer) i REST adapter.

Zasadniczo trzeba zastąpić metody extract* z JSONSerializer.

Obecnie wygląda to mniej więcej tak:

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

Wskazówki jak sprawdza json[root] - trzeba by napisać niestandardową metodę na podstawie przewidywanej odpowiedzi API.

Innym podejściem byłoby "preprocesowanie" json z interfejsu API w celu użycia elementu głównego. Możesz to zrobić, sprawdzając, jakie metody wywołują extract* (która przekazuje je json) i zanim to zrobi, zmodyfikuj json tak, aby zawierał element główny.

Mam nadzieję, że to pomoże, proszę dać mi znać, jeśli to nie jest jasne.

+0

Nicea odpowiedź. Dzięki! –

+0

Fantastyczne! Dziękuję Ci bardzo! To wydaje się działać: https://gist.github.com/richardkall/5910875 – Richard

-1

Próbowałem dodać root do json. Działa to dla mnie:

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

Manipulowanie odpowiedzią należy do serializera, a nie do adaptera. –

15

Można również normalizować go do czegoś, czego oczekują ember.

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

'type' nie jest już dostępny, tylko' payload'. http://emberjs.com/api/data/classes/DS.RESTSerializer.html # method_normalizePayload – rog

+0

To jest droga do rozwiązania, w porównaniu do zaakceptowanej odpowiedzi, ponieważ programista nie musi się martwić o typ ładunku (Array, Single object) i nie musi się martwić o operacje w sklepie. – kiddouk

+0

To jest właściwy pomysł, ale kod nie działa. Klucz wartości zwracanej to dosłownie "typKey", a nie wartość przechowywana przez 'var typKey'. – Andrew

1

Rozwiązałem to poprzez rozszerzenie DS.RESTSerializer. Metoda extractArray musi zostać przeciążona, gdy odpowiedzią serwera jest typ tablicy.

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