Ember.js REST adapter handling different JSON structure - javascript

I'm using REST adapter, when I call App.Message.find() Ember.js makes call to the /messages to retrieve all messages and expect to see JSON structure like this:
{
"messages": [] // array contains objects
}
However API I have to work with response always with:
{
"data": [] // array contains objects
}
I only found the way1 to change namespace or URL for the API. How to tell REST adapter to look for data instead of messages property?
If this is not possible how to solve this problem? CTO said we can adapt API to use with REST adapter as we want, but from some reason we can't change this data property which will be on each response.

Assuming you are ok with writing your own adapter to deal with the difference, in the success callback you can simply modify the incoming name from "data" to your specific entity -in the case above "messages"
I do something like this to give you and idea of what if possible in a custom adapter
In the link below I highlighted the return line from my findMany
The json coming back from my REST api looks like
[
{
"id": 1,
"score": 2,
"feedback": "abc",
"session": 1
},
{
"id": 2,
"score": 4,
"feedback": "def",
"session": 1
}
]
I need to transform this before ember-data gets it to look like this
{
"sessions": [
{
"id": 1,
"score": 2,
"feedback": "abc",
"session": 1
},
{
"id": 2,
"score": 4,
"feedback": "def",
"session": 1
}
]
}
https://github.com/toranb/ember-data-django-rest-adapter/blob/master/packages/ember-data-django-rest-adapter/lib/adapter.js#L56-57
findMany: function(store, type, ids, parent) {
var json = {}
, adapter = this
, root = this.rootForType(type)
, plural = this.pluralize(root)
, ids = this.serializeIds(ids)
, url = this.buildFindManyUrlWithParent(store, type, ids, parent);
return this.ajax(url, "GET", {
data: {ids: ids}
}).then(function(pre_json) {
json[plural] = pre_json; //change the JSON before ember-data gets it
adapter.didFindMany(store, type, json);
}).then(null, rejectionHandler);
},

Related

Is it appropriate to use Apollo local state to store a different representation of returned data

I have an Apollo Client that I'm using to request data from a service. I want to use the data I get in response to create a network of nodes and links e.g.
// Response data:
{
"Team": [
{
"name": "Example Team",
"members": [
{ "name": "Bob" },
{ "name": "Alice" }
]
}
]
}
// Network data:
{
"nodes": [
{ "name": "Example Team" }
{ "name": "Bob" },
{ "name": "Alice" }
],
"links": [
{ "source": "Example Team", "target": "Bob" },
{ "source": "Example Team", "target": "Alice" }
]
}
Historically, before using GraphQL, I would have used Redux to store the munged API response in state and read from there.
Is it appropriate to take a GraphQL result from Apollo and immediately save it back to Apollo local state in a different form so it can be queried by components in that format?
The main problem I foresee is that I think I'd have to query to check if the data I want exists in local state, then make another query if it didn't. In a Redux-world this would be wrapped up inside my store which would then only make the request off to the API if it didn't have the data it needed which 'feels' much cleaner.
In my case this could be solved using Afterware in Apollo Client, see this answer for more information.
It would allow me to munge the returned data into the form I need, and return it in the response alongside the original data.

Display json response in ajax jquery,

The JSON Response I'm getting,
{
"user_data": {
"id": 22,
"first_name": xxx,
"last_name": xxx,
"phone_number": "123456789",
},
"question_with_answers" : [
{
"id": 1,
"question_name": "Features of our project that you like (select one
or more):",
"answers": [
{
"id": 19,
"question_id": 1,
"customer_id": 22,
"option": "Location",
},
{
"id": 20,
"question_id": 1,
"customer_id": 22,
"option": "Architecture",
},
]
},
{
"id": 2,
"question_name": "Features of our project that you DID NOT like
(select one or more):",
"answers": [
{
"id": 22,
"question_id": 2,
"customer_id": 22,
"option": "Location",
},
]
},
{
"id": 3,
"question_name": "How soon are you looking to buy a new home?",
"answers": [
{
"id": 24,
"question_id": 3,
"customer_id": 22,
"option": "Immediately",
}
]
}
]
}
So that is how JSON response looks like, now I need to display data using jquery
My js code
function openModal(Id){
var CustomerId = Id;
$.ajax({
type : 'get',
url: 'customer-details',
data: {
'CustomerId':CustomerId
},
success: function(data)
{
//what I have to do here
}
})
}
The output I want is,
first_name : xxx
last_name : xxx
phone_number : 123456789
1.Features of our project that you like (select one or more):
ans: Location, Architecture
2.Features of our project that you DID NOT like (select one or more)
ans: Location
3.How soon are you looking to buy a new home?
ans: Immediately
Thats how my output should look like from above json response,Is it possible to get above output using that Json response I got
There are two variable that I have passed from backend like user_data and question_with_answers
In success handler first of all make your json into a array using
var obj = JSON.parse(data);
Now in data you have array of your response and you can use this like
obj.first_name
obj.last_name
Note:- may be you have issue in JSON.parse so use first
var data = json.stringify(data)
after that use Json.parse function and use above data variable
this data
You have to set the dataType in the $.ajax call, set it to dataType:"json"...
After that, you got on the data variable in the success the json object and you can access it like data.user_data or data.id or data.first_name.
If you dont define the json as dataType, it will not work properly.
Addition
If you want to display the content of "question_with_answer" you have to iterate trough it, like ....
for (i in data.question_with_answer) { alert(data.qestion_with_answer[i]); }

JSON list optimization

I want to create a JSON API that returns a list of objects. Each object has an id, a name and some other information. API is consumed using JavaScript.
The natural options for my JSON output seems to be:
"myList": [
{
"id": 1,
"name": "object1",
"details": {}
},
{
"id": 2,
"name": "object2",
"details": {}
},
{
"id": 3,
"name": "object3",
"details": {}
},
]
Now let's imagine that I use my API to get all the objects but want to first do something with id2 then something else with id1 and id3.
Then I may be interested to be able to directly get the object for a specific id:
"myList": {
"1": {
"name": "object1",
"details": {}
},
"2": {
"name": "object2",
"details": {}
},
"3": {
"name": "object3",
"details": {}
},
}
This second option may be less natural when somewhere else in the code I want to simply loop through all the elements.
Is there a good practice for these use cases when the API is used for both looping through all elements and sometime using specific elements only (without doing a dedicated call for each element)?
In your example you've changed the ID value from 1 to id1. This would make operating on the data a bit annoying, because you have to add and remove id all the time.
If you didn't do that, and you were relying on the sorted order of the object, you may be in for a surprise, depending on JS engine:
var source = JSON.stringify({z: "first", a: "second", 0: "third"});
var parsed = JSON.parse(source);
console.log(Object.keys(parsed));
// ["0", "z", "a"]
My experience is to work with arrays on the transport layer and index the data (i.e. convert array to map) when required.

Backbone .fetch() adds one too many models

I am using backbone's fetch method to retrieve a set of JSON from the server. Inside the fetch call, I have a success callback that correctly assigns attributes to a model for each object found.
var foo = assetCollection.fetch({
reset: true,
success: function(response){
var data = response.models[0].attributes.collection.items;
data.forEach(function(data){
assetCollection.add([
{src_href: data.data[0].value,
title: data.data[1].value
}
]);
});
console.log(assetCollection.models)
}
})
Right now I am working with a static set of JSON that has two objects. However, logging assetCollection.models returns three objects: the first is the initial server JSON response, while the next two are correctly parsed Backbone models.
How do I keep Backbone from adding the first object (the entire response from the server) to its set of models, and instead just add the two JSON objects that I am interested in?
The JSON object returned from the server is as follows:
{
"collection": {
"version": "1.0",
"items": [
{
"href": "http://localhost:8080/api/assets/d7070f64-9899-4eca-8ba8-4f35184e0853",
"data": [
{
"name": "src_href",
"prompt": "Src_href",
"value": "http://cdn.images.express.co.uk/img/dynamic/36/590x/robin-williams-night-at-the-museum-498385.jpg"
},
{
"name": "title",
"prompt": "Title",
"value": "Robin as Teddy Roosevelt"
}
]
},
{
"href": "http://localhost:8080/api/assets/d7070f64-9899-4eca-8ba8-4f35184e0853",
"data": [
{
"name": "src_href",
"prompt": "Src_href",
"value": "http://b.vimeocdn.com/ts/164/830/164830426_640.jpg"
},
{
"name": "title",
"prompt": "Title",
"value": "Mrs. Doubtfire"
}
]
}
]
}
}
You should modufy collection.
Probably you should change parse method:
yourCollection = Backbone.Collection.extend({
parse: function(data) {
return data.models[0].attributes.collection.items;
}
})
When you use fetch Backbone parse result and add all elements what you return in parse.

How to create Backbone collection from following json array?

I am getting a following JSON(/users.json) which contains users:
[
[
{ "id": "43343", "project_id": "1", "username": "Amy" }
{ "id": "34244", "project_id": "1", "username": "Tommy" }
],
[
{ "id": "76575", "project_id": "2", "username": "Izzy" }
{ "id": "13322", "project_id": "2", "username": "Sam" }
],
{ "id": "09983", "project_id": "3", "username": "Max" }
]
When project has one user I get one user hash which is not in array.
I would like to build a Backbone collection with all users. How to do that?
You provide an array of arrays of users. So to fetch all users in the init method, you can give it data but as an array of users, i.e. you will flatten this original array of arrays once with underscore flatten method :
data = _(data).flatten(true);
Then the collection constructor will natively understand your json array.
But maybe you already do this transformation in the fetching method and this is not the problem you are facing..
If you have defined a collection (say userCollection) with a user model you should be able to simply do something like this:
var col;
$.getJSON("/users.json", function(data) {
col = new userCollection(data);
});
This would more likely be done in the fetch function of the collection, but the principle here is that you can pass an array of objects to a collection and it will marshal all from json to backbone models.

Categories

Resources