How to Unwrap Json data in angular? - json

I have a Json data in this format
I want to parse this data in angular typescript when I am calling the rest API. How to do it.
Here this part is my java class object which I want to convert to my model class array.
"gameId": 66,
"kashScore": 0,
"samScore": 1,
"wonBy": "Sam",
"createUserId": 0,
"lastModifiedUserId": 0,
"creationDate": "2020-04-20T14:05:44.263+0000",
"lastModifiedDateTime": "2020-04-20T14:05:44.264+0000",
"sessionId": 1000,
"count": null
My model class
And this information is for tracking pagination.
I tried something like this, but it gives error as:-

Your response is just an array. The data that represents Fifa[] is the first item in the response array.
The HttpClient won't magically convert it for you. If you want to return Fifa[] from your service, then you need to map your response to that type.
return this.http.get<any[]>(fifaUrl).pipe(
map((response: any[]) => response[0])
);
EDIT
You have stated that you want to return all information from the response. In that case you should return an object that implements GetResponse from service function (and probably think about a more suitable name).
fetchAllGamesRecordPaginate(
pageNumber: number, pageSize: number
): Observable<GetResponse> {
const fifaUrl = ${this.baseUrl}/demo/pageNumber/${pageNumber}/pageSize/${pageSize};
return this.httpClient.get(fifaUrl).pipe(
map((response: any[]) => {
const pagination = response[1];
return {
fifa: response[0],
totalRecord: pagination.totalRecord,
pageSize: pagination.pageSize,
pageNumber: pagination.pageNumber,
totalPages: pagination.totalPages
};
})
);
}
Here I am mapping the response array to an object that implements GetResponse.

If you want the method to just return an Observable<Fifa[]> you should use a map operator on your Observable:
return this.httpClient.get<GetResponse>(fifaUrl).pipe(
map((response) => response.fifa)
);

update the return type to Observable<GetResponse> then you need to map the respond to GetResponse structure
fetchAllGamesRecordPaginate(pageNumber:number,pageSize: number):Observable<GetResponse>{
const fifaUrl = ${this.baseUrl}/demo/pageNumber/${pageNumber}/pageSize/${pageSize};
return this.httpClient.get(fifaUrl)
.pipe(([fifa,paginationInfo]) => (
{
fifa ,
...paginationInfo
}
)
);
}
the api return an array with two items the first is the fifa[] and the
second is an object with pagination information

Related

Using Axios to parse JSON objects containing only values without keys

I am trying to parse this json into two separate arrays
{"2022-08-11":11561.71,"2022-08-12":11396.5433,"2022-08-13":10875.3483,"2022-08-14":10036.1867,"2022-08-15":10307.895,"2022-08-16":10358.7683,"2022-08-17":10220.6033,"2022-08-18":10321.7317,"2022-08-19":10924.965,"2022-08-20":10776.9083,"2022-08-21":10133.3483}
currently I managed to get the object using axios on Vue, however I am struggling to seperate the strings of dates from the integer values in the arrDate and arrValue empty arrays
data: () => ({
arrDate: [],
arrValue: [],
totalVuePackages: null
}),
created(){
axios.get("https://api.coindesk.com/v1/bpi/historical/close.json?start=2019-01-01&end=2019-12-31").then(
response => this.totalVuePackages = response.data);
}
}
You can simply use Object functions :
this.arrDate = Object.keys(response.data)
this.arrValue = Object.values(response.data)
If you want to put the keys in one array and the values in another, use the following
// your Axios response
const response = {data:{"2022-08-11":11561.71,"2022-08-12":11396.5433,"2022-08-13":10875.3483,"2022-08-14":10036.1867,"2022-08-15":10307.895,"2022-08-16":10358.7683,"2022-08-17":10220.6033,"2022-08-18":10321.7317,"2022-08-19":10924.965,"2022-08-20":10776.9083,"2022-08-21":10133.3483}};
// Reduce the entries (key / value pairs) into two separate arrays
const [dates, numbers] = Object.entries(response.data).reduce(
([keys, values], [key, value]) => [
[...keys, key],
[...values, value],
],
[[], []]
);
console.log("dates", dates);
console.log("numbers", numbers);
// then assign to your Vue data with
// this.arrDate = dates;
// this.arrValue = numbers;
.as-console-wrapper { max-height: 100% !important; }

Angular 9 mapping a json response to array

I have this interface
export interface Student {
cf: string,
firstName: string,
lastName: string,
dateOfBirth: Date,
description?: string,
enrollmentDate?: Date
}
I want to populate an array of students with a http get request, which returns the following json for each student
{cf: "blablabla", first_name: "Mario", last_name: "Rossi", date_of_birth: "1998-01-24", enrollment_date: "2019-03-20" },
As you can see, the interface has different names from the response (firstName instead of first_name), so when I print to the console the names of the students I get undefined.
This is the service function from which I get the data
getStudents(): Observable<Student[]> {
return this.httpClient.get<Student[]>(this.studentsUrl, this.baseService.httpOptions);
}
And here is my students component
export class StudentsComponent implements OnInit {
students: Student[];
childIcon = faChild;
plusIcon = faPlus;
private _newStudent: boolean = false;
constructor(private studentsService: StudentsService) { }
ngOnInit(): void {
this.studentsService.getStudents().subscribe(
(result: Student[]) => {
this.students = result;
this.students.forEach(student => console.log(student));
},
error => console.log(error)
)
}
}
Is there a way to convert the json response to my Student interface? Several answers on stack overflow suggest map is the way, but I don't understand how to use that operator alog with subscribe
One way would be manually loop through the array and define new keys and delete obsolete ones before returning the array using RxJS map.
Service
import { pipe } from 'rxjs';
import { map } from 'rxjs/operators';
getStudents(): Observable<Student[]> {
return this.httpClient.get<Student[]>(this.studentsUrl, this.baseService.httpOptions).pipe(
map(response => response.forEach(student => {
student.firstName = student.first_name;
student.lastName = student.last_name;
student.dateOfBirth = student.date_of_birth;
student.enrollmentDate = student.enrollment_date;
delete student.first_name;
delete student.last_name;
delete student.date_of_birth;
delete student.enrollment_date;
});
)
);
}
But depending on the number of elements in the array, this could be a heavily taxing operation for a single HTTP request. Couldn't you define the interface definition to match the one of the API?

How do I use rxjs map to mutate data in object before casting a new type from an object gotten from a HttpClient request?

Hope the title isn't too specific.
The back-end I am working with returns Dates as a string. I have a function to convert that string to a javascript Date object. I use a Rxjs map to convert the json response to my Typescript objects like so.
getAllRecordsByEmployeeId(employeeId: number): Observable<Record[]> {
return this.http.get<Record[]>(
this.basePath
+ this.recordPath
+ this.recordEmployeeIdParam
+ employeeId,
this.httpOptions)
.pipe(
map((res: any) => res.records as Record[]),
);
}
I want to mutate res.records.startDate with a function before it gets turned into a Record object. How can I accomplish this?
getAllRecordsByEmployeeId(employeeId: number): Observable<Record[]> {
return this.http.get<Record[]>(
I understand, that your http request does not actually return a Record array. It returns an object with a Record Array field, which is basically another Record model. It is very similar, but it's a different model.
Please consider changing it to:
interface RecordFromApi extends Record {
startDate: string; // overwrite attribute
}
interface RecordResponse {
records: RecordFromApi[];
}
getAllRecordsByEmployeeId(employeeId: number): Observable<Record[]> {
return this.http.get<RecordResponse>(
this.basePath
+ this.recordPath
+ this.recordEmployeeIdParam
+ employeeId,
this.httpOptions)
.pipe(
map((res: RecordResponse) => res.records.map(record => mapRecord(record))), // mapRecord is a custom function which maps RecordFromApi model to Record model
);
}
We do something similar in my application. But instead of returning
res.records as Record[]
we do something like this:
.pipe(
map((records: Record[]) => records.map(records => new Record(record)))
);
and then on the record.ts
export class Record {
/*
properties
*/
date: Date;
constructor(params: Partial<Record> = {}) {
this.date = new Date(params.date);
}
}
This way you actually get instances of your class and you can use any functions you may have in your class (that's the issue we had when we came up with this solution).

Returning Array of objects using RxJS map operator

I have one third Party API which returns data as below - It has been called from Angular Service using HttpClient.
const someObject = {
employees:[
{name:"XYZ",age:30},
{name:"ABC",age:28},
]
}
Now I have one interface with structure as below -
interface EmployeeData{
campus:{
property1:string;
property2:string;
};
details:{
name:string;
age:number
}
}
So EmployeeData.details exactly mimics someObject.employees structure
Now I want to return data from my service as below -
getData():Observable<EmployeeData[]>{
}
So , employees array from someObject should map to EmployeeData.details
and this should be returned as EmployeeData[].
How can I achieve this ?
I have tried below approach but it is giving different results.
getData():Observable<EmployeeData[]> {
return this.http.get<any>(url).pipe(
tap(value => console.log(value)),
map(data => data.employees),
map(employees =>{
return employees.map(employee =>{
return{
details:{
name:employee.name,
age:employee.age,
}
}
}
}
)
}
What it returns is -
details:{}
details:{}
But what I want is :
{
details:{}
}
{
details:{}
}
Can anybody please help here ?
If you want to type the function with Observable<EmployeeData>, your returned Observable must contain an array of objects implementing the EmployeeData interface, meaning that you will need to define them fully, not just the details property.
If you can't define all properties at this time, you have to use a type assertion with the as keyword. Be aware that you will lose type safety and might run into errors because missing properties will be undefined.
getData(): Observable<EmployeeData[]> {
return this.http.get<any>(url)
.pipe(
map(data => data.employees),
map(employees => employees.map(employee => ({ details: employee } as EmployeeData)))
);
}
See it in action here : https://stackblitz.com/edit/angular-msd6ym

Angular 2 - Getting object id from array and displaying data

I currently have a service that gets an array of json objects from a json file which displays a list of leads. Each lead has an id and when a lead within this list is clicked it takes the user to a view that has this id in the url ie ( /lead/156af71250a941ccbdd65f73e5af2e67 )
I've been trying to get this object by id through my leads service but just cant get it working. Where am I going wrong?
Also, i'm using two way binding in my html.
SERVICE
leads;
constructor(private http: HttpClient) { }
getAllLeads() {
return this.http.get('../../assets/leads.json').map((response) => response);
}
getLead(id: any) {
const leads = this.getAllLeads();
const lead = this.leads.find(order => order.id === id);
return lead;
}
COMPONENT
lead = {};
constructor(
private leadService: LeadService,
private route: ActivatedRoute) {
const id = this.route.snapshot.paramMap.get('id');
if (id) { this.leadService.getLead(id).take(1).subscribe(lead => this.lead = lead); }
}
JSON
[
{
"LeadId": "156af71250a941ccbdd65f73e5af2e66",
"LeadTime": "2016-03-04T10:53:05+00:00",
"SourceUserName": "Fred Dibnah",
"LeadNumber": "1603041053",
},
{
"LeadId": "156af71250a999ccbdd65f73e5af2e67",
"LeadTime": "2016-03-04T10:53:05+00:00",
"SourceUserName": "Harry Dibnah",
"LeadNumber": "1603021053",
},
{
"LeadId": "156af71250a999ccbdd65f73e5af2e68",
"LeadTime": "2016-03-04T10:53:05+00:00",
"SourceUserName": "John Doe",
"LeadNumber": "1603021053",
}
]
You didn't used the newly created leads array (const leads is not this.leads), so do this:
getLead(id: any) {
return this.getAllLeads().find(order => order.LeadId === id);
}
And change your map to flatMap, because from the server you get an array, but you have to transform it to a stream of its items:
getAllLeads() {
return this.http.get('../../assets/leads.json').flatMap(data => data);
}
Don't forget to import it if you have to: import 'rxjs/add/operator/flatMap';
You can have getLead in your component level itself since you are not making any api to get the information. In your component,
this.lead = this.leads.find(order => order.id === id);
or to make the above service work, just do leads instead of this.leads
const lead = leads.find(order => order.id === id);