Brand new to react-native and typescript!
I'm have a bit of trouble extracting JSON response. I was to extract the response and put it into a class as shown below.
Here is the request code
let notifications: INotification[]
notifications = (await Requests.GET('notification/user/test-user-1', accessToken));
Here is the class
export interface INotification {
id: string;
senderId: string;
receiverId: string;
text: string;
isSeen: boolean;
type: string;
timestamp: string;
}
Here is the Postman response
{
"notifications": [
{
"pk": "user-1",
"sk": "notification1234",
"entity": "notification",
"id": "id number",
"senderId": "test-user-2",
"receiverId": "test-user-1",
"text": "Test notifications",
"isSeen": false,
"type": 2
}
]
}
Here is response from the console
{ notifications:
[ { pk: 'user#test-user-1',
sk: 'notification1234',
entity: 'notification',
id: 'id number',
senderId: 'test-user-2',
receiverId: 'test-user-1',
text: 'Test notifications',
isSeen: false,
type: 2 } ]
}
I want to be able to write out:
console.log("TEXT: ",notifications[0].text )
And get the response of : "Text: Test notifications"
Any help welcome!
the data is in an array you need to pass the array first
console.log("TEXT: ", notifications[0].text);
Related
I would like to create an instance of the Customer class from Json object.
But using the plainToInstance function of class-transformer I don't have the proper class instance as a type save typescript object.
What I'm doing bad?
Import
import { plainToInstance } from 'class-transformer';
Customer JSON
const json = `{
"id": "1",
"name": "Jogn",
"surname": "Doe",
"email": "j.doe.test#gmail.com",
"phone": "123456789"
}
}
`;
Customer class definition
import { Field, ObjectType, Directive, ID } from '#nestjs/graphql';
import { Address } from './address';
#ObjectType()
#Directive('#key(fields: "id")')
export class Customer {
#Field(() => ID)
id: string;
#Field()
name: String;
#Field({nullable: true})
surname?: String;
#Field()
email: String;
#Field({nullable: true})
phone?: String;
#Field()
customerType: String;
#Field()
customerStatus: String;
#Field(() => [Address], { nullable: true })
addresses?: [Address]
}
Transformation from Json to Customer instance
let customer : Customer = plainToInstance(Customer, json) as Customer;
console.log('customer.email);
Console result
Customer email: undefined
So I couldn't get the email of the customer here
This is what I have when I log the entire customer variable
console.log(customer);
{
"id": "1",
"name": "Jogn",
"surname": "Doe",
"email": "j.doe.test#gmail.com",
"phone": "123456789"
}
Test with creating the Customer instance inline
var x = new Customer();
x.id = "123";
console.log(x)
So, now the object looks properly in the console
Customer { id: '123' }
You must pass a json object to plainToInstance - not a string.
i.e. your json variable should be
const json = {
id: '1',
name: 'Jogn',
surname: 'Doe',
email: 'j.doe.test#gmail.com',
phone: '123456789',
};
here's a working Stackblitz example
The second attribute of plainToInstance should be a plain object so you have to parse your json string into an object:
let customer = plainToInstance(Customer, JSON.parse(json))
I am trying to create an accordion from the JSON data.
I am calling the GET request from json-server and successfully able to call the API.
I am not able to access the properties of the children in the variable tileData which shows the error:
Property 'children' does not exist on type 'Tile[]'.
Not sure where I am going wrong.
tileData!: Tile[];
getTileData() {
this.tileService.showTile().subscribe((data: any) => {
this.tileData = data;
console.log('this.tileData.children.name :>> ', this.tileData.children.name ); //Shows error
});
}
The function in service file is
showTile() {
return this.http.get<Tile[]>('http://localhost:3000/data');
}
I have created an interface to store the obtained JSON data which is shown below:
export interface Tile {
name: string;
image: string;
children: { name: string; image: string; url: string };
}
My JSON data received as follows:
{
"data": [
{
"name": "First",
"image": "https://img.freepik.com/free-vector/football-2022-tournament-cup-background_206725-604.jpg?size=626&ext=jpg",
"children": [
{
"name": "Firstone",
"image": "https://img.freepik.com/free-vector/hand-painted-watercolor-abstract-watercolor-background_23-2149005675.jpg?size=626&ext=jpg",
"url": "http://www.google.com"
},
{
"name": "Firsttwo",
"image": "https://img.freepik.com/free-vector/hand-painted-watercolor-abstract-watercolor-background_23-2149005675.jpg?size=626&ext=jpg",
"url": "http://www.google.com"
},
{
"name": "Firstthree",
"image": "https://img.freepik.com/free-vector/hand-painted-watercolor-abstract-watercolor-background_23-2149005675.jpg?size=626&ext=jpg",
"url": "http://www.google.com"
}
]
},
{
"name": "Second",
"image": "https://img.freepik.com/free-vector/football-2022-tournament-cup-background_206725-604.jpg?size=626&ext=jpg",
"children": [
{
"name": "Secondone",
"image": "https://img.freepik.com/free-vector/hand-painted-watercolor-abstract-watercolor-background_23-2149005675.jpg?size=626&ext=jpg",
"url": "http://www.google.com"
},
{
"name": "Secondtwo",
"image": "https://img.freepik.com/free-vector/hand-painted-watercolor-abstract-watercolor-background_23-2149005675.jpg?size=626&ext=jpg",
"url": "http://www.google.com"
},
{
"name": "Secondthree",
"image": "https://img.freepik.com/free-vector/hand-painted-watercolor-abstract-watercolor-background_23-2149005675.jpg?size=626&ext=jpg",
"url": "http://www.google.com"
}
]
}
]
}
Issue 1
Your JSON response was an object containing the data property with Tile[].
Use map from rxjs to return as Observable<Tile[]>.
import { map } from 'rxjs';
showTile() : Observable<Tile[]> {
return this.http.get<any>('http://localhost:3000/data')
.pipe(map((response: any) => response.data));
}
Issue 2
While the children property is an array but not an object.
export interface Tile {
name: string;
image: string;
children: { name: string; image: string; url: string }[];
}
Issue 3
To print out the name, you need to iterate titleData and iterate children array from each title object.
getTileData() {
this.tileService.showTile().subscribe((data: any) => {
this.tileData = data;
for (let title of this.tileData) {
for (let child of title.children) {
console.log('title.children.name :>> ', child.name);
}
}
});
}
Demo # StackBlitz
You haven't mentioned the error but, the interface definition should use exact name as you have in data.
try
export interface Tile {
name: string;
image: string;
children: { name: string; image: string; url: string };
}
Here is my json file
{
"data": [
{
"firstName": "Tom",
"lastName": "Yoda",
"type": "guest",
"id": "0",
"gender": m,
"data": { "age": 26, "born": "UK" }
},
]
}
This data array could have more entries.
I have to map the values into an interface which looks like:
InterfacePerson {
id: string;
title: string;
firstName: string;
lastName: string;
age: string;
location: string;
}
I am unable to change the interface. So I'm trying to do some pseudo coding.
const list;
list = convertToInterfacePerson = (value): Array<InterfacePerson> => {
return {
id: value.id,
title: if(value.gender === "m")? "Mr" : "Mrs",
firstName: value.firstName,
lastName: value.lastName,
age: value.data.age,
//...
}
}
I think you were trying to use a conversion mapping function called convertToInterfacePerson but you hadn't set it up yet (separately from trying to use it). The code below shows it declared and used within a map Array method call. I believe this resolves the error(s) you were getting.
// Copied in the JSON for demonstration
const sourceJson = {
"data": [
{
"firstName": "Tom",
"lastName": "Yoda",
"type": "guest",
"id": "0",
"gender": "m",
"data": { "age": 26, "born": "UK" }
},
]
};
// Declared the InterfacePerson interface
interface InterfacePerson {
id: string;
title: string;
firstName: string;
lastName: string;
age: string;
location: string;
}
// Declared the conversion mapping function (optional parameter typing included)
const convertToInterfacePerson = (value: { firstName: string, lastName: string, type: string, id: string, gender: string, data: { age: number, born: string } }): InterfacePerson => {
return {
id: value.id,
// Removed the `if` statement due to ternary conditional
title: ((value.gender === "m") ? "Mr" : "Mrs"),
firstName: value.firstName,
lastName: value.lastName,
// Wrapped the value.data.age in a string conversion
age: String(value.data.age),
location: value.data.born
};
}
// Declared and assigned the list based on the returned array from the mapping function (each element is applied in the `convertToInterfacePerson` function)
const list = sourceJson.data.map(convertToInterfacePerson);
// Show the result of the conversion
console.log(JSON.stringify(list, null, 2));
And for a live example, check out this TypeScript Playground script containing this solution.
I am receiving a json response in an Angular 11 app and I have created an interface corresponding to that json object. The json object is
{
"division": {
"uid": "f5a10d90-60d6-4937-b917-1d809bd180b4",
"name": "Sales Division",
"title": "Sales",
"type": "Form",
"formFields": [
{
"id": 1,
"name": "firstName",
"label": "First Name",
"value": "John"
},
{
"id": 2,
"name": "lastName",
"label": "Last Name",
"value": "Smith"
}
]
}
}
The typescript interface I created for this json object is
export interface FormField {
id: number;
name: string;
label: string;
value: string;
}
export interface Division {
uid: string;
name: string;
title: string;
type: string;
formFields: FormField[];
}
export interface Division {
division: Division;
}
I am using a service division.sevice.ts to fetch the above json response from API and everything works fine. I am trying to write unit tests for the this service in the division.service.spec.ts file. I created a mockDivisionObj inside this file for testing purpose which is shown below.
mockDivisionObj = {
"division": {
"uid": "f5a10d90-60d6-4937-b917-1d809bd180b4",
"name": "Sales Division",
"title": "Sales",
"type": "Form",
"formFields": [
{
"id": 1,
"name": "firstName",
"label": "First Name",
"value": "John"
},
{
"id": 2,
"name": "lastName",
"label": "Last Name",
"value": "Smith"
}
]
}
}
An error is shown which says
Property 'division' is missing in type '{ uid: string; name: string; title: string; type:
string; formFields: { id: number; name: string; label: string; value: string; }[]; }' but
required in type 'Division'.
I think the way I created the interface may be wrong but I couldn't figure out what exactly is causing the issue. Please help me out with this.
I was able to fix the issue by changing the name of one of the interfaces in the file to 'AppDivision' as shown below.
export interface FormField {
id: number;
name: string;
label: string;
value: string;
}
export interface Division {
uid: string;
name: string;
title: string;
type: string;
formFields: FormField[];
}
export interface AppDivision {
division: Division;
}
The same name for two interfaces caused the error in the unit test mock object.
Your code is fine.To solve this error you can try the code below =>
this.division = this.mockDivisionObj.division as Division;
Check the Link: StackBlitz Demo link.
I've currently got a local JSON file which holds the data for numerous properties. The idea is to load this JSON file into my app, and display it into a list with options to sort it (aka rearrange the data).
Here's my property.model.ts
export class Property {
ID: number;
description: string;
price: string;
agreementType: string;
streetName: string;
houseNumber: number;
postCode: string;
place: string;
image: Image[];
status: string;
constructionYear: number;
areaSize: number;
numberOfRooms: number;
numberOfBedrooms: number;
garageType: string;
garageCapacity: number;
}
export class Image {
ID: number;
base64: string;
}
This is what my json file looks like:
[
{
"ID": 1,
"description": "Lorem ipsum...",
"price": "€800,25",
"agreementType": "unknown",
"streetName": "street",
"houseNumber": 55,
"postCode": "postCode",
"place": "place",
"image": [
{
"ID": 1,
"base64": ""
},
{
"ID": 2,
"base64": ""
},
{
"ID": 3,
"base64": ""
}
],
"status": "status",
"constructionYear": 1999,
"areaSize": 50,
"numberOfRooms": 5,
"numberOfBedrooms": 2,
"garageType": "",
"garageCapacity": 0
},
{
//...
}
]
and here is my property.service.ts
export class PropertyService {
public propertyData: Observable<Property>;
constructor(private http: HttpClient) {
this.propertyData = this.observableJson();
}
observableJson() : Observable<Property> {
return this.http.get('/data/property.json')
.map((res:Response) => { res.json(); console.log(res.json())})
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
}
Later on, I want to be able to use my service elsewhere within the app as well, to (for instance) add a property object to it or something. Though I don't know if this is possible like that. But for now I just want to be able to somehow have my obserable array be useable in the property component. Which, at the moment, doesn't seem to work because when I use console.log(JSON.stringify(this.propertyData)); inside the constructor, I get the following error:
JS: ERROR Error: Uncaught (in promise): TypeError: Converting circular structure to JSON
JS: TypeError: Converting circular structure to JSON
now, a google search tells me that this is because it's a nested JSON object, but after many attempts I haven't been able to work out how to solve this.
Thanks in advance for any help.
The property Observable probably has something self-referential inside of it which results in the error you're seeing. You don't want to JSON.stringify propertyData which is an Observable, but you want to stringify the emitted JSON response. There are a lot of different ways to do this and it depends on the circumstances of where you are using it. For example:
this.propertyData.subscribe(data => JSON.stringify(data));
const data = JSON.stringify(await this.propertyData.toPromise());
Try this -
this.observableJson().subscribe(res => {
this.propertyData = res;
console.log(JSON.stringify(this.propertyData));
});