Get contents of json file not working - json

I want to get a json object from a json file using angular 2 http.get. What I end up getting from the file is this:
t_isScalar: falseoperator: tsource: t__proto__: Object
Here is my code
#Injectable()
export class ValidateJSONSchemaService {
constructor(private http: Http) { }
getSchema(fileName): any {
return(this.http.get(fileName)
.map(this.extractData)
);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
}
How do I fix getSchema to make it return the json object rather than this: t_isScalar: falseoperator: tsource: t__proto__: Object. Note that when I change the file name it returns the same thing. I would have expected an informational error (I did do error handling but the code never errors out).

You need to subscribe to observable:
#Injectable()
export class ValidateJSONSchemaService {
constructor(private http: Http) { }
getSchema(fileName): any {
return(this.http.get(fileName)
.map(this.extractData).subscribe(data => console.log(data));
);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
}

In addition to Maciej s answer you can use the | async pipe that does the subscribing for you.
<div>{{getSchmea('fileName') | async}}</div>

Related

Facing issues on accessing json() in angular, HttpClient. Looking for alternatives

I would like to get all the posts from 'https://jsonplaceholder.typicode.com/posts'.
However the update of Http to HttpClient, not allowing to access "json()" (at response.json()).
Please guide for a solution.
Regards.
export class PostsComponent {
posts: any[];
constroctur(http: HttpClient) {
http
.get('https://jsonplaceholder.typicode.com/posts')
.subscribe((response) => {
this.posts = response.json();
});
}
}
The best way is the pass the data type to the response argument "response : any[]".
export class PostsComponent {
posts: any[];
constroctur(http: HttpClient) {
http
.get('https://jsonplaceholder.typicode.com/posts')
.subscribe((response : any[]) => {
this.posts = response;
});
}
}
You must set the content type along with the request. It should look like below.
const headers = { 'Content-Type': 'application/json'};
export class PostsComponent {
posts: any[];
constroctur(http: HttpClient) {
http
.get('https://jsonplaceholder.typicode.com/posts',{headers})
.subscribe((response : any[]) => {
this.posts = response;
});
}
}
http
.get('https://jsonplaceholder.typicode.com/posts')
.subscribe((response) => {
this.posts = response;
});
All you need to do, and arguably the best choice is setting the posts to the response. It's already a JavaScript object.
If, for whatever reason you require a JSON string, then you can look into JSON.Stringify:
this.posts = JSON.stringify(response)

Angular HTTP GET

I have a server running on "localhost:3000". It displays data as JSON at e.g. "localhost:300/locations".
My "data.service.ts" includes this code:
path: string = 'http://localhost:3000'
constructor(private http: HttpClient) { }
// Locations
getAllLocations(): Observable<Location[]> {
let location = null;
this.http.get(this.path + '/locations')
.map((res => location = res))
.catch((error: any) => Observable.throw(console.log(error)));
return location;
}
In my result.component.ts I'm running this code:
constuctor(private dataservice: DataService) { }
ngOnInit() {
console.info(this.dataservice.getAllLocations());
}
I'm expecting to get as output all Locations as JSON, instead of this the output is "null".
Does anyone have a suggestion on how to make this work properly?
UPDATE:
Also tried this for the HTTP call:
getAllLocations(): Observable<Location[]> {
this.http.get<Location[]>(this.path + '/locations')
.pipe(
tap(items => console.info('fetched items'))
);
}
The output for this code is unfortunately: "Object { _isScalar: false, source: {...}, operator: {...} }"
Did you know that HttpClient#get returns an Observable? You can just return the get method in your method.
Secondly, you can set an interface to the method so that it'll return the JSON as typed.
Lastly, you can use template literals in your API URL.
/**
* Retrieves a list of locations.
* (TODO: Add better documentation here)
*/
getAllLocations(): Observable<Location[]> {
return this.http.get<Location[]>(`${this.path}/locations`);
}
You can then handle this in the actual component that calls this method:
constuctor(private dataservice: DataService) { }
ngOnInit() {
this.dataservice.getAllLocations().subscribe(result => {
console.log(result);
});
}
You have to return Observable from the service:
path: string = 'http://localhost:3000'
constructor(private http: HttpClient) { }
// Locations
getAllLocations(): Observable<Locations[]> {
return this.http.get(this.path + '/locations').pipe(
map((res => location = res)),
catch((error: any) => Observable.throw(console.log(error))));
}
And subscribe to it in the component.
constructor(private dataservice: DataService) { }
ngOnInit() {
this.dataservice.getAllLocations().subscribe(result => {
console.log(result);
})
}

How can I save http get response object in angular 6

I'm new to angular and i'm trying to figure out how can I save in a local variable the response of http.get(url)
Here is my code :
export class AppComponent {
private url = 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=MY_KEY&format=json&artist=The+Weeknd' ;
public data;
constructor(private http: HttpClient) {
this.http.get(this.url).subscribe(response => this.data = response);
console.log(this.data); // -> The result is undefined...
}
}
At first, I tried this.http.get(this.url).subscribe(response => console.log(response)); and that was working has expected, however an assignation doesn't work.
Thanks a lot !
You're code is exactly correct. The reason the console.log is not showing the response value is because it is running BEFORE the response is processed. Once the HTTP request has been started, JavaScript continues executing the current function.
If you want to log the response, you need to do so inside the response handler
export class AppComponent {
private url = 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=MY_KEY&format=json&artist=The+Weeknd' ;
public data;
constructor(private http: HttpClient) {
this.http.get(this.url).subscribe(response => {
this.data = response;
console.log(this.data);
});
}
}
You are doing async HTTP call. so you need to add console.log inside subscribe.
export class AppComponent {
private url = 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=MY_KEY&format=json&artist=The+Weeknd' ;
public data;
constructor(private http: HttpClient) {
this.http.get(this.url).subscribe(response => {
this.data = response;
console.log(this.data);
});
}

Read data from a local JSON file with data binding in ngOnInit() results in undefined variable

I am trying to get a data from json file in the assets folder, and then assign this data to a variable that will be binded to another #Input variable of a child componenet.
Code
Based on multiple solutions on the net, I retrieve my JSON data this way:
#Injectable()
export class JSONService {
constructor(private http: HttpClient) { }
public fromJSON(jsonFileName: string): Observable<any[]> {
let result: any[] = new Array();
let pathToJson: string = "assets/" + jsonFileName + ".json";
return this.http.get(pathToJson).map(data => {
let result: any[] = new Array();
// Apply some treatment on data and push it to the result array
return result;
});
}
}
I then call my service in the ngOnInit() method of the parent component:
ngOnInit() {
this.jsonService.fromJSON("users.json").subscribe(fields => {
this.fields= fields;
console.log(this.fields); // Log (I): this.fields is well defined
});
console.log(this.fields); // Log (II): this.fields is undefined
}
Where the variable fields is binded to a child component:
<child-component [childFields] = "fields"></child-component>
Problem
The problem that I am facing is that the asynchronous call to the fromJSON method causes this.fields to be undefined at some point of the lifecycle of the page execution (Log (II) from the code above), and this causes to send an undefined value of the this.fields variable to the child component.
How to avoid to have an undefined value of the fields variable, and make sure that the child component is always loaded with the data from the json file?
Just add *ngIf to check if the data is loaded
<child-component *ngIf="fields" [childFields] = "fields"></child-component>
Service.ts
#Injectable()
export class JSONService {
constructor(private http: HttpClient) { }
public fromJSON(jsonFileName): Observable<any[]> {
console.warn('Retriving Default Data from File.......');
return this.http.get(filename)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || [];
}
private handleError(error: any) {
const errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
console.log('Server Error!');
return Observable.throw(errMsg);
}
}
parent.component.ts
constructor(public jsonService: jsonService) {
}
ngOnInit() {
this.jsonService.fromJSON('assets/users.json').subscribe(
function (success) {
this.data = success;
this.datahandle(success);
},
error => console.log('Getting Server Data Error :: ' +
JSON.stringify(error)));
}
datahandle(jsonData){
console.log('check data' + JSON.stringify(jsonData)); <-----check data
// may parse your jsonData if required
this.fields = jsonData ;
let keys = Object.keys(jsonData);
console.log(keys);
}
}
parent.component.html
<child-component *ngIf="fields" [childFields] = "fields"></child-component>
Assuming your component is somewhat like below
export class SomeComponent implements OnInit {
public fields: any[];
ngOnInit() {
this.jsonService.fromJSON("users.json").subscribe(fields => {
this.fields = fields;
console.log(this.fields); // Log (I): this.fields is well defined
});
console.log(this.fields); // Log (II): this.fields is undefined
}
}
Then you can either initialize fields with an empty array
public fields: any[] = [];
OR in template
<child-component *ngIf="fields" [childFields]="fields"></child-component>

Can't bind objects from json to angular 2 class

I am new to Angular 2 and I am trying to create service which send get request and gets json. And bind those result from json to array of angular classes. But when there is trouble and something went wrong.
I followed documentation on angular.io and did everything like there. Through debugger I found that when i write
return body.data
after that object that returns is undefined.
I got next error:
Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
Please help me with this issue.
Json data:
[{"categoryId":1,"categoryName":"cpu"},{"categoryId":2,"categoryName":"gpu"},{"categoryId":3,"categoryName":"motherboard"},{"categoryId":4,"categoryName":"phone"},{"categoryId":5,"categoryName":"hdd"},{"categoryId":6,"categoryName":"ssd"},{"categoryId":7,"categoryName":"ram"},{"categoryId":8,"categoryName":"rom"}]
Entity class:
export class Category {
constructor(public categoryId: number, public categoryName: string) {}
}
Service class:
#Injectable()
export class CategoryService {
private currentUrl = 'http://localhost:8081/emusicshop/api/categories';
constructor (private http: Http) {}
getCategories(): Observable<Category[]> {
return this.http.get(this.currentUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
Component:
Component
export class CategoryComponent implements OnInit {
allCategories: Category[];
constructor(private service: CategoryService) { }
getCategories(): void {
this.service.getCategories().subscribe(
categories => this.allCategories = categories);
}
ngOnInit() {
this.getCategories();
}
}
HTML file:
<ul>
<li *ngFor="let categ of allCategories">
Id : {{categ.id}}
Name : {{categ.name}}
</li>
</ul>
Your response object does not have a data field. It should be more like this:
private extractData(res: Response) {
let body = res.json();
return body || []; //<-- return an empty array instead of an object so *ngFor won't complain about iteration
}
And try the safe navigation operator on your template ?
<ul>
<li *ngFor="let categ of allCategories">
Id : {{categ?.categoryId}}
Name : {{categ?.categoryName}}
</li>
</ul>