I have an Employee model in my emberjs app, and I am trying to load the Employees content using a RESTful web service which come in the following format:
{
"Result": [
{
"EmployeeId": "1",
"EmployeeName": "Mark Smith",
"Active": 0,
"Dept": "Sales"
},
{
"EmployeeId": "2",
"EmployeeName": "John Smith",
"Active": 1,
"Dept": "Sales"
},
{
"EmployeeId": "3",
"EmployeeName": "Michael Smith",
"Active": 1,
"Dept": "Administration"
}
],
"ResultCount": 3
}
Here I am facing 3 problems:
Is it possible to read this JSON format and add it to the Employee model, I understand that "Result" should have been "Employees" but I have no control over the return JSON format so if it is possible to use "Result" that will be great. Any example on doing so is highly appreciated.
How can I handle "ResultCount"? Is there a way I can read it as part of Employee model?
How I can read "Active" in the app View as "Active" / "Not Active" instead of 0 or 1?
Thanks for your time
As pointed out by jasonpgignac, you'll need to write a custom serailizer/deserializer to get the data into ember-data.
Once you have your data loaded ResultCount isn't required. You should use the 'length' property on the returned collection.
As part of your serializer you'll want to convert 0/1 to false/true in your model. You can them add a property like:
activeLabel: ( ->
if #get('active')
'Active'
else
'Not Active'
).property('active')
and use this property in your templates.
As requested, here's a sample class from a project of mine:
App.StudentSerializer = DS.ActiveModelSerializer.extend
serializeBelongsTo: (record, json, relationship) ->
key = relationship.key
if key is 'attendance'
#serializeAttendance(record, json)
else
json["#{key}_id"] = record.get("#{key}.id")
serializeAttendance: (record, json) ->
attendance = record.get('attendance')
json['attendance'] = {}
['monday', 'tuesday', 'wednesday', 'thursday', 'friday'].forEach( (day) =>
json['attendance'][day] = attendance.get(day)
)
serializeHasMany: (record, json, relationship) ->
key = relationship.key
jsonKey = Ember.String.singularize(key) + '_ids'
json[jsonKey] = []
record.get(key).forEach( (item) ->
json[jsonKey].push(item.get('id'))
)
My store.coffee looks like:
App.Store = DS.Store.extend
# Override the default adapter with the `DS.ActiveModelAdapter` which
# is built to work nicely with the ActiveModel::Serializers gem.
adapter: '_ams'
App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
You'll probably want to use the JsonAdapter and extend it if you don't have any control over the backend. As I said below, I haven't done deserialising but there should be the necessary hooks for you to convert into the format required by ember-data.
Related
iam currently developing a contact management system web app using ember js for the front end .Iam using ember store for fetching the data from the api , while fetching json data using store.findAll() , iam getting the json array with the length of data as expected but when i try to access the data at a specific position in the json array it gives undefined value , it is not giving the model value.I have checked everything like json format , naming conventions with respect to my serializer but cant able to find what is going wrong , can anyone help me with solving this ?
Application adapter :
import RESTAdapter from '#ember-data/adapter/rest';
export default class ApplicationAdapter extends RESTAdapter {
buildURL(...args) {
return "http://localhost:8082/ContactManagementSystem1/api/contact/5";
}
headers = {
'Accept': '*/*',
};
}
Json response from api :
[
{
"firstName": "Example",
"lastName": "K",
"deletedAt": "",
"mobileNumberHome": "7827382738",
"companyName": "Example",
"dateOfBirth": "2000-04-12",
"id": 21,
"userId": 4,
"mobileNumberWork": "2738273788",
"email": "rath#gmail.com"
},
{
"firstName": "nameexample2",
"lastName": "p",
"deletedAt": "",
"mobileNumberHome": "8989898996",
"companyName": "Business ",
"imageURL": "actress1.jfif",
"dateOfBirth": "2021-10-05",
"id": 51,
"userId": 4,
"mobileNumberWork": "8667889896",
"email": "nameexample2h#gmail.com"
}
]
Serializer :
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeResponse(store, primaryModelClass,payload,id,requestType){
arguments[2] = {
"contacts" : payload
}
return this._super(...arguments);
}
});
Since my json response is different from the RestSerializer format i have written some code in the serializer for normalising the response.
Route where i fetch data using store.findAll()
import Route from '#ember/routing/route';
import {inject as Service } from '#ember/service';
export default class UserContactRoute extends Route {
#Service store;
async model() {
return this.store.findAll('contact');
}
}
These are codes which i have used , i have also checked in the inspect's console no error is been thrown , the problem is model array object were undefined.
One should use the objectAt(index) for accessing array elements because those arrays are not regular JS ones. See here:
It's important to note that RecordArray is not a JavaScript array,
it's an object that implements MutableArray. This is important
because, for example, if you want to retrieve records by index, the []
notation will not work--you'll have to use objectAt(index) instead.
I have a JSON object with an array (it is from the body of an HTTP response) that looks similar to the following:
{"people": [
{
"name": "john",
"city": "chicago",
"age": "22"
},
{
"name": "gary",
"city": "florida",
"age": "35"
},
{
"name": "sal",
"city": "vegas",
"age": "18"
}
]}
I'm trying to retrieve the "city" or "age" values by looking for a "name." e.g., when "name" = "sal," I'd expect to get "vegas" to be returned if I was asking for "city" or "18 if I had requested for "age." I'm attempting to do this in Groovy.
Don't even know where to start with the code. First time dealing with a JSON array. Any assistance is much appreciated.
I would recommend starting by reading Parsing and producing JSON documentation page. You will learn about the powerful groovy.json.JsonSlurper class that allows you to work with JSON documents efficiently.
When you create a JSON object representation with a method like:
def json = new JsonSlurper().parseText(rawJson)
You can access JSON document fields in the same way you access object properties. For instance, json.people will return you a list of people. Then, you can call the method like find(predicate) which returns a first result that matches the given predicate from a list. In this case, you can call something like:
def person = json.people.find { it.name == "sal" }
The it is a variable that keeps a reference to the object in the iteration process. It means that find iterates the list and searches for the first object that matches it.name == "sal".
When you find the person associated with the name, you can extract city and age fields in the same way as you would access object fields, e.g.
println person.age // prints 18
println person.city // prints vegas
Here is the full example:
import groovy.json.JsonSlurper
def rawJson = '''{"people": [
{
"name": "john",
"city": "chicago",
"age": "22"
},
{
"name": "gary",
"city": "florida",
"age": "35"
},
{
"name": "sal",
"city": "vegas",
"age": "18"
}
]}'''
def json = new JsonSlurper().parseText(rawJson) // creates JSON object
def person = json.people.find { it.name == "sal" } // finds the first person with name "sal"
assert person.city == "vegas" // calling person.city returns a city name
assert person.age == "18" // calling person.age returns age of a person
To learn more about processing JSON documents with Groovy, consider reading the documentation page I attached above. It will help you understand more complex use cases, and it will help you gain confidence in working with parsing JSON documents using Groovy. I hope it helps.
In my Django webapp, I have Function Based API that display a list for with pagination. The problem is I want each row in the list to have expanded output of relational field.
This is my model for attendance:
class Attendance(models.Model):
CHECKIN = 1
CHECKOUT = 2
ATTENDANCE_TYPE_CHOICES = (
(CHECKIN, "Check In"),
(CHECKOUT, "Check Out"),
)
employee = models.ForeignKey(Employee)
company = models.ForeignKey(Company)
activity_type = models.IntegerField(choices = ATTENDANCE_TYPE_CHOICES, default=CHECKIN)
This is part of my list API where I define what fields I want to display and is paginated.
employee_list = Employee.objects.filter(company = auth_employee.employee.company.id).values("id","employee","company","activity_type").order_by('id')
page = request.GET.get('page', request.POST['page'])
paginator = Paginator(employee_list, request.POST['page_limit'])
try:
employees = paginator.page(page)
except PageNotAnInteger:
employees = paginator.page(request.POST['page'])
except EmptyPage:
employees = paginator.page(paginator.num_pages)
return Response(list(employees), status=status.HTTP_200_OK)
The output is a list like this but without employee detail.
[
{
"id": 14,
"employee": 15,
"company": 15,
"activity_type": 1,
},
{
"id": 15,
"employee": 15,
"company": 15,
"activity_type": 2,
}
]
My expected output, how do I get something like this ?
[
{
"id": 14,
"employee": {
"id":"2",
"name":"Michael"
},
"company": 15,
"activity_type": 1,
},
{
"id": 15,
"employee": {
"id":"2",
"name":"Jeniffer"
},
"company": 15,
"activity_type": 2,
}
]
How can I produce a list that shows the relational data like above to display in the json response ?
What you're describing is serialization, in this case nested serialization in which django model relationship references get serialized in the structure you described above.
There's no out of the box way to do this with django. The django-rest-framework project has solved this issue with their nested serializers
If you're working on an API that will be outputting the results to JSON to be consumed by some service or client other than Django's templates, I would seriously consider adding that to your project.
I have the following response coming from a request
[
{
"id": 3767,
"sellerName": "abc",
"siteActivity": [
{
"siteId": -1,
"siteName": "example.com",
"categories": [
{
"categoryId": 79654,
"parentId": null,
"name": "Photo & Picture Frames",
"siteName": null,
"channelType": null
},
{
"categoryId": 114397,
"parentId": null,
"name": "Chests of Drawers",
"siteName": null,
"channelType": null
},
{
"categoryId": 11707,
"parentId": null,
"name": "Jewellery Boxes",
"siteName": null,
"channelType": null
},
{
"categoryId": 45505,
"parentId": null,
"name": "Serving Trays",
"siteName": null,
"channelType": null
}
]
}
]
},
{
"id": 118156,
"sellerName": "xyz",
"siteActivity": [
{
"categoryId": 45505,
"parentId": null,
"name": "Serving Trays",
"siteName": null,
"channelType": null
}
]
}
]
Now, I need to extract "id" values and "categoryId" values and send them as list in the next request body.
Currently, I am using JSON Path Extractor with the expression
$.[*].id
to get my hand on all ids and
$.[*].siteActivity.[categoryId]
for category ids.
Next, I want to use the above values and send them as parameters in request body.
Currently, I am able to extract only one id with
$.[0].id
and then assigning it to variable "id" and using the following in request body
{"ids":[{"id":"${id}"}]}
but I want to be able to send
{"ids":[{"id":"${id}"},{"id":"${id2}"}....]}
There is no limit on how many ids can be there, so I cannot hardcode and need something dynamic to do the aggregation. What kind of processor can help me here? Please add some example if you can.
I believe that you should be able to use Beanshell PostProcessor for building the request.
Given your sample data your $.[*].id JSONPath Expression should return the following values:
id=[3767,118156]
id_1=3767
id_2=118156
So basically you need to:
Determine "id" count
Populate dynamic JSON Object to send
Store it to JMeter variable for later use
In order to do so add a Beanshell PostProcessor after JSONPath Extractor and put the following code into its "Script" area
import net.sf.json.JSONArray;
import net.sf.json.JSONObject; // necessary imports
JSONObject data2Send = new JSONObject();
JSONArray array = new JSONArray(); // instantiate JSON-related classes
int idCount = vars.get("id").split(",").length; // get "id" variables count
for (int i = 1; i <= idCount; i++) { // for each "id" variable
JSONObject id = new JSONObject(); // construct a new JSON Object
id.put("id", vars.get("id_" + i));// with name "id" and value id_X
array.add(id); // add object to array
}
data2Send.put("ids",array); // add array to "ids" JSON Object
vars.put("myJSON", data2Send.toString()); // store value as "myJSON" variable
You can refer to your {"ids":[{"id":"3767"},{"id":"118156"}]} data as ${myJSON} where required.
The approach will play for any number of "id" variables.
References:
Welcome to Json-lib
How to use json-lib
Json-lib JavaDoc
How to use BeanShell: JMeter's favorite built-in component
I'm using Factual api to fetch location data. Their restful service return data in JSON format as follow, but they are not using "usual" JSON format. There's no attribute key, instead, there's a “fields” that explains all the field keys.
So the question is how to retrieve the attribute I need? Please give an example if possible. Thanks in advance.
{
"response": {
"total_rows": 2,
"data": [
[
"ZPQAB5GAPEHQHDy5vrJKXZZYQ-A",
"046b39ea-0951-4add-be40-5d32b7037214",
"Hanko Sushi Iso Omena",
60.16216,
24.73907
],
[
"2TptHCm_406h45y0-8_pJJXaEYA",
"27dcc2b5-81d1-4a72-b67e-2f28b07b9285",
"Masabi Sushi Oy",
60.21707,
24.81192
]
],
"fields": [
"subject_key",
"factual_id",
"name",
"latitude",
"longitude"
],
"rows": 2,
"cache-state": "CACHED",
"big-data": true,
"subject_columns": [
1
]
},
"version": "2",
"status": "ok"
}
If you know the field name, and the data isn't guaranteed to stay in the same order, I would do a transform on the data so I can reference the fields by name:
var fieldIndex = {}
for (key in x.response.fields)
{
fieldIndex[x.response.fields[key]] = key;
}
for (key in x.response.data)
{
alert(x.response.data[key][fieldIndex.name]);
}
// Field map
var _subject_key = 0,
_factual_id = 1,
_name = 2,
_latitude = 3,
_longitude = 4;
// Example:
alert(_json.response.data[0][_factual_id]);
Demo: http://jsfiddle.net/AlienWebguy/9TEJJ/
I work at Factual. Just wanted to mention that we've launched the beta of version 3 of our API. Version 3 solves this problem directly, by including the attribute keys inline with the results, as you would hope. (Your question applies to version 2 of our API. If you're able to upgrade to version 3 you'll find some other nice improvements as well. ;-)