I am having difficulties retrieving data from .json file in this format, I have tried headers, changing URL but it is not working:
{
"cars": ["BMW", "Mercedes", "Fiat"],
"testDrives": [
{
"start": "2020-02-03T11:00:00.000Z",
"end": "2020-02-03T16:00:00.000Z",
"name": "Bmw"
},
{
"start": "2020-02-03T09:00:00.000Z",
"end": "2020-02-03T12:30:00.000Z",
"name": "Mercedes"
}
]
}
My code:
data = '../../assets/test.json';
constructor(private http: HttpClient) { }
getData() {
this.http.get(this.data).subscribe(data => {
console.log(data);
});
}
I keep getting this error:
error
You need to define an interface with required properties to specify the response type
export interface ResponseModel{
cars: string;
testDrives: string;
}
and specify Response type in subscribe
getData() {
this.http.get(this.data).subscribe((data: ResponseModel) => {
console.log(data);
});
}
Related
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 };
}
I have tried a lot but I am not able to get endpoint response mapped to my model. I am using HttpClient and Angular4.
I got data back from service but it is not mapped correctly to my model class.
I have following JSON which service is Returning:
{
"result": [
{
"id": "1",
"type": "User",
"contactinfo": {
"zipcode": 1111,
"name": "username"
}
}
]
}
I have created a model in typescript which I will like to map to json response:
export interface result {
zipcode: number;
name: string;
}
This is how i call JSON endpoint.
result : string[] = [];
constructor(private http: HttpClient) { }
public getList(): result[] {
this.http.get<result[]>('url...', { headers: this.headers }).subscribe(
data => {
// 1. Data is returned - Working
console.log('data: ' + data);
this.result= data;
// This is the problem. My data is not mapped to my model. If I do following a null is returned
console.log('data mapped: ' + this.result[0].name);
},
(err: HttpErrorResponse) => {
// log error
}
);
return this.result;
}
You need to import the interface in your component,
import { result } from '.result';
Your interface should look like,
interface RootObject {
result: Result[];
}
interface Result {
id: string;
type: string;
contactinfo: Contactinfo;
}
interface Contactinfo {
zipcode: number;
name: string;
}
and change the type of result as,
result : result;
and assign the result as,
this.result = data;
You can use http://www.jsontots.com/ to create the interface based on JSON
your "data" is an Object, with a property "result". result[] has a property called "contactInfo". in contactInfo you have the data you want, so
//you have no model, so NOT get<result[]>
this.http.get('url...', { headers: this.headers }).subscribe(
data => {
this.result= data.result[0].contactInfo;
}
in my angular2 component
keyword_test={};
getData() {
this.service.getData()
.subscribe(
data => {
this.keyword_test = data
console.log(data);
console.log(this.keyword_test);
});
}
console.log(data) and console.log(this.keyword_test) print right data like this
{
"caption": "folder0",
"type": "folder",
"subnodes": [
{
"caption": "folder1",
"type": "folder",
"subnodes": [
{
"caption": "keyword1",
"type": "keyword",
"search_filter_expression": "sfe1"
},
{
"caption": "keyword2",
"type": "keyword",
"search_filter_expression": "sfe2"
}
]
},
{
"caption": "folder2",
"type": "folder",
"subnodes": [
{
"caption": "keyword3",
"type": "keyword",
"search_filter_expression": "sfe3"
},
{
"caption": "keyword4",
"type": "keyword",
"search_filter_expression": "sfe4"
}
]
}
]
}
but in my ngOnInit
ngOnInit() {
this.getData();
console.log(this.keyword_test);
}
despite the this.getdata(), this.keyword_test print "Object {}" i think none object.
Is the keyword_test initialized incorrectly?
when i print console.log(typeof data) in getData function, result is string...
I did change it to json in service, but I do not know why.
++and this is my service
#Injectable()
export class keywordService {
private API_URI: string = 'MYAPIURL';
constructor(private http: Http) {
}
getData() {
return this.http.get(this.API_URI, {body: ""})
.map(res => {res.json();
});
}
}
ngOnInit() {
this.getData(); // this execute but data arrives with call back
console.log(this.keyword_test); //this execute before data has arrived and thats why it is not printing the result from success call
}
Correct way
this.service.getData()
.subscribe(
data => {
this.keyword_test = data
console.log(data);
console.log(this.keyword_test);
});
I am trying to map the received JSON-data on my created Models. The problem is, that the JSON-data has nested arrays. So it is not possible to map my data with the way I am trying to. Is there a mistake in my way or is there a better way to map my JSON-data ?
JSON-Data
{
"data": {
"apiName": "test-application",
"stages": [
{
"stage": "prod",
"id": "xxxxxxxx",
"methods": [
{
"id": "xxxxxx",
"path": "/users/create",
"httpMethods": [
"GET"
],
"methodName": "testMethod",
"url": "https://xxxx/xxxxx/xxxxxx"
}
]
},
{
"stage": "dev",
"id": "xxxxxxx",
"methods": [
{
"id": "xxxxxxx",
"path": "/users/create",
"httpMethods": [
"GET"
],
"methodName": "testMethod",
"url": "https://xxxxx/xxxxxx/xxxx"
}
]
}
]
}
}
Models:
import {ApiStage} from "./ApiStage";
export class Api {
constructor(values: Object = {}){
Object.assign(this, values);
}
public apiName: string;
public stages: ApiStage[];
}
import {ApiMethod} from "./ApiMethod";
export class ApiStage {
constructor(values: Object = {}){
Object.assign(this, values);
}
public stage: string;
public id: string;
public methods: ApiMethod[];
}
export class ApiMethod {
constructor(values: Object = {}){
Object.assign(this, values);
}
public id: string;
public path: string;
public httpMethods: string[];
public methodName: string;
public url: string;
}
HTTP-method in service:
getApi() {
return this.http.post(this.url, this.data, {headers: this.headers})
.map(this.extractData)
.map(api => new Api(api))
.catch((error: any) => Observable.of(error.json().error || 'Server error'));
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
JSON has just a very limited set of data types - string, number, boolean, array, object. If you want to convert a JSON object tree to a tree of objects of your custom classes, it's necessary to do it recursively and with creating correct objects - not working with objects that just look like being of your classes.
This process can be tedious and error prone, so it's better to use a library such as Class transformer (https://github.com/pleerock/class-transformer) which can do it for you. You just annotate your classes with decorators (such as #Type(...)) and then you can transform plain JSON objects using plainToClass() method or serialize real objects to JSON using classToPlain().
i'm new to Typescript and javascript.
My question is:
how from this
```
{
"release": {
"ref": {},
"commits": {}
},
"debug": {
"ref": {},
"commits": {}
},
"feature": {
"ref": {},
"commits": {}
},
"hotfix": {
"ref": {},
"commits": {}
}
}
```
map it with with Typescript using interfaces
export interface IRepo {
branches: IBranch; // how to make branches a of type string: IBranch dictionary?
}
there will be unknown number of properties like debug, release, etc,
i want to keep them as dictionary in IRepo instance
i'm using this to fetch data:
```
getRepo() : Observable<IRepo> {
if (!this.repo) {
return this.http.get(this._baseUrl + 'repo.json')
.map((res: Response) => {
this.repo = res.json();
return this.repo;
})
.catch(this.handleError);
} else {
return this.createObservable(this.repo);
}
}
```
You have a map that goes from some known string to an object of known structure (has ref commits). Just use a string indexer:
interface BranchByName {
[branchName: string]: {
ref: any;
commits: any;
}
}