Reputation: 4067
The Ember.js REST Adapter expects the JSON to be returned as:
{
"person": {
"first_name": "Barack",
"last_name": "Obama",
"is_person_of_the_year": true
}
}
But my API returns the data without a root element:
{
"first_name": "Barack",
"last_name": "Obama",
"is_person_of_the_year": true
}
Is it possible to customize the REST Adapter so that it accepts my JSON data? Right now it's showing "Assertion failed: Your server returned a hash with the key 0 but you have no mapping for it"
UPDATE: Based on Sherwin Yu's answer below, this is what I came up with, seems to work so far: https://gist.github.com/richardkall/5910875
Upvotes: 7
Views: 7861
Reputation: 636
The easiest way is to not use the RESTSerializer but the much simpler JSONSerializer, which does not expect a root element.
Good resources on understanding which serializer to use for a given API can be found in these two blog posts:
http://thejsguy.com/2015/12/05/which-ember-data-serializer-should-i-use.html
http://emberigniter.com/fit-any-backend-into-ember-custom-adapters-serializers/
Upvotes: 1
Reputation: 11
I solved this by extending DS.RESTSerializer. extractArray method needs to be overloaded when server response is array type.
App.PersonSerializer = DS.RESTSerializer.extend({
extractSingle: function (store, type, payload, id) {
var wrappedObj = {};
wrappedObj[type.typeKey] = payload;
return this._super(store, type, wrappedObj, id);
}});
Upvotes: 1
Reputation: 37075
You could also normalize it into something ember would expect.
App.PersonSerializer = DS.RESTSerializer.extend({
normalizePayload: function(type, payload) {
var typeKey = type.typeKey;
return {
typeKey: payload
}
}
});
Upvotes: 15
Reputation: 3230
Yes, you can write your own custom REST adapter. Take a look at the source code in the JSONSerializer, RESTSerializer (which extends the JSONSerializer), and the REST adapter.
Basically, the you need to override the extract*
methods from the JSONSerializer.
Currently, it looks something like this:
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]);
}
},
Notice how it checks json[root]
-- you'd have to write your custom method based on your expected API response.
Another approach would be to "preprocess" the json from the API to use a root element. You could do this by finding out what methods call extract*
(which passes it the json) and before it does so, modify the json to contain the root element.
Hope this helps, please let me know if it's unclear.
Upvotes: 8