parsing JSON into a Angular 2 object - json

I am having the following issue.
I have a very large JSON string that has all the variables from the object.
object:
export class User {
ssn:string;
userId:string;
firstName:string;
lastName:string;
middleName:string;
office:string;
role:string;
lockCode:string;
command:string;
street:string;
city:string;
position:string;
zip:string;
phone:string;
dsn:string;
fax:string;
email:string;
pwEffectiveDate:any;
pwVaildationDate:any;
fromDate:any;
toDate:any;
systemAccess:string;
dmType:string;
accessInfoEffectiveDate:any;
accessInfoEffectiveTo:any;
availableOffices: string[];
availbleRole:string[];
}
JSON :
#Injectable()
export class SearchService {
getData() :any[] { return [
{"snn": "26999935-7", "userId": "EVD404", "firstName": "Chaney", "lastName": "Vernon", "middleName": "X", "office": "ADURT", "role": "GC", "lockCode": "Q", "command": "5th Grp", "street": "953-1348 Faucibus Rd.", "city": "Bienne-lez-Happart", "position": "Developer", "zip": "76222", "phone": "233-969-1834", "dsn": "359-887-4719", "fax": "157-376-6377", "email": "mauris.rhoncus#rhoncusDonec.com", "pwEffectiveDate": "13/03/17", "pwVaildationDate": "27/01/18", "fromDate": "10/11/17", "toDate": "21/12/17", "systemAccess": "GC", "dmType": "XJ", "accessInfoEffectiveDate": "26/12/2016", "accessInfoEffectiveTo": "06/06/2016", "availableOffices": "UUU", "availbleRole": "GC"},
{"snn": "43250813-7", "userId": "NSB626", "firstName": "Addison", "lastName": "Vernon", "middleName": "X", "office": "AUTRO", "role": "GC", "lockCode": "O", "command": "11th ACR", "street": "Ap #904-5416 Semper, Road", "city": "s Herenelderen", "position": "Developer", "zip": "26457", "phone": "890-600-3144", "dsn": "679-122-1054", "fax": "913-500-7495", "email": "Aenean#molestiesodales.com", "pwEffectiveDate": "11/06/17", "pwVaildationDate": "01/03/17", "fromDate": "05/08/17", "toDate": "29/09/16", "systemAccess": "LIMIT", "dmType": "NB", "accessInfoEffectiveDate": "19/04/2017", "accessInfoEffectiveTo": "13/04/2016", "availableOffices": "LLL", "availbleRole": "USER"},
Then I want to be able to call methods like below when I pass my service into the component:
getUserByLastName(lastName):User[]{
let temp: User[]=[];
for(let d of this.data) {
if(d.lastName == lastName){
temp.push(d);
}
}
return temp;
}
I have tried to JSON.parse but that did not work. I tried a few other things but none seem to stick.
---------------------------------Update 1----------------------------
It has been brought to my attention that I should be using an Observable. Here is what I have in trying to implement that but it is currently not working:
getUserBySSN():Observable<User[]> {
return this._http.get(this._url)
.map((response: Response) => response.json())
.do(data => console.log("User data" + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(error: Response) {
console.log(error);
return Observable.throw(error.json().error || 'Internal Server error');
}
I created a json file and set the variable url as its path. However I am getting to following error:
The type argument for type parameter 'T' cannot be inferred from the
usage. Consider specifying the type arguments explicitly. Type
argument candidate 'Response' is not a valid type argument because it
is not a supertype of candidate 'Response'. Types of property 'type'
are incompatible. Type 'string' is not assignable to type 'ResponseType'
It was suggested I use .map((response: Response) => <User[]> response.json()) but I was not allow to convert it.
After further research I found this is the the best approach and am trying to get it to function so later on I can use it to do actual HTTP calls against the DB.

In the world of Angular2, you should be using rxjs to achieve your requirement, as shown below
Your component should subscribe to the service values as below
this.userService.getUsers()
.filter(users =>{
for(let user of users) {
if(user.lastName == 'Vernon'){
this.users.push(user);
}}})
.subscribe(users => this.users = users,
error =>this.errorMessage =<any> error);
Your service should raise http calls and return data as below
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import {User} from './user.model.ts';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';
#Injectable()
export class UserService {
private _url = "src/data.json";
constructor(private _http: Http) {
}
getUsers(): Observable<User[]> {
return this._http.get(this._url)
.map((response: Response) => <User[]>response.json())
.do(data => console.log("User data" + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(error: Response) {
console.log(error);
return Observable.throw(error.json().error || 'Internal Server error');
}
}
Also, you should not use Class for holding your data model, instead use interface as shown in the demo below.
LIVE DEMO

Related

getServerSideProps error: Unexpected token < in JSON at position 0

I'm using next.js and I want to fetch data from my data1.json file via getStaticProps(). The problem is that I get the error:
FetchError: invalid json response body at http://localhost:3000/data/data1.json reason: Unexpected token < in JSON at position 0
I have following code:
trainings.js (projectfolder/pages/trainings.js)
export default function Trainings({ data }) {
console.log(data);
return (
<main>
<h1>My trainings</h1>
</main>
);
}
export async function getServerSideProps() {
const res = await fetch('http://localhost:3000/data/data1.json');
const data = await res.json();
return { props: { data } };
}
data1.json (projectfolder/data/data1.json)
[
{
"name": "Jescie Duncan",
"email": "nunc#protonmail.couk",
"address": "Ap #666-9989 Nisi Avenue"
},
{
"name": "Karen Bartlett",
"email": "tellus.imperdiet#aol.couk",
"address": "P.O. Box 787, 2857 Tincidunt Ave"
},
{
"name": "Teegan Valdez",
"email": "lacus.mauris.non#hotmail.edu",
"address": "Ap #474-300 Nullam Avenue"
},
{
"name": "Stuart Silva",
"email": "nulla.donec.non#google.edu",
"address": "336-2367 Eu Ave"
}
]
Please check whether http://localhost:3000/data/data1.json api is working or not. Because Nextjs support React components as default support in the pages folder not JSON. If you want serve as API you need to use NextJS api routes which you need to specifically put logic inside api folder.
in api/data/data1.js file
import data from '/path/to/json'
async function handler(req, res) {
return res.status(200).json(data)
}
export default handler;
But a better approach is:
As you have JSON file, you directly import that data in trainings.js rather than calling an API.
import data from 'path/to/json';
export async function getServerSideProps() {
return { props: { data } };
}

Why are there data types included in this JSON response?

I'm consuming an API via React-Native, and data-type strings are being included in the JSON response as such:
{"volumeInfo": Object {
"allowAnonLogging": false,
"authors": Array [
"Tim Mathers",
],
"canonicalVolumeLink": "https://market.android.com/details?id=book-ZzOPDwAAQBAJ",
"categories": Array [
"Sports & Recreation",
]}
Notice the "Object" and "Array" type strings included in the response.
When I curl the same exact endpoint from my CLI, I get correctly formatted JSON as such:
{"volumeInfo": {
"title": "Baseball",
"subtitle": "America's Diamond Mind, 1919-1941",
"authors": [
"Richard C. Crepeau"
],
"publisher": "U of Nebraska Press",
"publishedDate": "2000"}
The data from curl is not only coming back in the correct format, but also in a completely different order than my application. This leads me to believe that my implementation is the cause. See code below
Action
export function searchBooks(book)
{
const url = `${BASE_URL}q=${book}&filter=free-ebooks&key=${API_KEY}`;
return dispatch => {
dispatch(getData());
fetch(url)
.then(blob => blob.json())
.then(data => {
console.log(data)
dispatch(getDataSuccess(data))
})
.catch(e => {
console.log(e);
dispatch(getDataFailure(e.message))
});
}
}
Reducer
const initialState = {
payload:[],
fetching: false,
error: false
}
export default function(state=initialState, action){
switch (action.type){
case FETCHING_DATA: return {payload:[], fetching: true, ...state}
case FETCH_SUCCESS: return {payload:[action, ...state]}
case ERROR: return {payload:[], error: true, ...state}
}
return state;
}
Thank you for any clarification as to why data types are included in my JSON, and how my implementation could be the reason.

Angular5 HTTPclient get issue with nested json

HttpClient.get in Angular 5 is not returning data if data is in a nested json format. The code below works for non-nested json data.
Would you please let me know if I miss anything or what would be a way to get the data?
Code:
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
export class ReportService {...
searchByUser(userUrl: string): Observable<any> {
console.log('userUrl', userUrl);
return this.httpClient
.get(userUrl, { responseType: 'json' })
.catch((error: HttpErrorResponse) => {
return Observable.throw(error.status)
});
}
}
import { ReportService } from '../report.service';
this.reportService.searchByUser(userUrl).subscribe(data => {
console.log("Data :", data);
});
Nested JSON Sample Data returned by the userUrl:
[
{
"userId": "JX",
"location": "CHANTILLY, XX",
"fullName": "SMITH, JX L",
"userType": "P",
"userStatusDesc": "Active",
"occupationInfo": {
"occupationTitle": "HR GENERALIST HQ"
},
"miscInfo": {
"rankingPoints": 15,
"searchTermCount": 1
}
}
]
It looks like the issue was not with the HttpClient or nested JSON. I was able to have it working with the same JSON generated locally. And when I deployed the code it worked with the JSON generated under the same proxy.

How to get the length of JSON array?

I have a json url with a response of the following kind
[
{
"gender": "Female",
"age": 7,
"class": 2,
"subject": [
"",
"",
""
]
},
{
"gender": "Female",
"age": 8,
"class": 3,
"subject": [
"ab",
"cd",
"ef"
]
},
...
]
I want to find the length of this array
so in the angular app I am using
export class CustomComponent implements OnInit {
length: number;
constructor() {
this.length = Object.keys('www.url...').length;
console.log(length);
}
in .html I have
<p>{{ length }}</p>
I am getting 61 whereas the actual length is 44, but the console on the other hand is showing 0.
Where am I going wrong?
Any kind of help would be greatly appreciated. Thanks.
Easiest method.
import { Http } from '#angular/http';
export class CustomComponent implements OnInit {
length: number;
constructor(private http: Http){
this.http.request('www.url...',{method:'GET'}).map(response => response.json()).subscribe(result=>{
this.length=result.length;
});
}
}
Issue here is you are trying to execute Object.keys on url and not on
data , your url will be considered as string.
Solution is to use HttpClient :
// First get data from external url and then perform all operation
this.http.get('www.url...').subscribe(data => {
this.length = data.length;
console.log(length);
});

Angular calling API with observable is not displaying data

I have implemented an angular 5 application to bring data from a Web API. I am using an observable to get the json. The Json coming from the API looks like this:
{
"Job": [
{
"Title": "Solution Architect",
"Summary": "Solution Architect",
"Salary": {
"MinValue": "100",
"MaxValue": "100",
"Text": "",
"Period": "HourlyRate"
},
"Reference": "234483_1",
},
{
"Title": "Senior Business Analyst – eCommerce ",
"Summary": "Senior Business Analyst...",
"Salary": {
"MinValue": "80",
"MaxValue": "100",
"Text": "",
"Period": "HourlyRate"
},
"Reference": "234874_1",
}
],
"Advertiser": "Resourcing",
"Source": "Wiz"
}
I have created a service looks as follows:
....
#Injectable()
export class AdvDataService {
private _getAddsUrl = 'https://xx.xxxx.com/v1/adverts/www111';
constructor(private _http: Http) { }
getAdvForClient(): Observable<IAdv> {
return this._http.get(this._getAddsUrl)
.map((response: Response) => <IAdv>response.json())
.do(data => console.log('All:' + data))
.catch(this.handleError);
}
The component looks like that:
....
export class HomeComponent implements OnInit {
constructor(private _sdvDataService: AdvDataService) { }
private loadAdverts: IAdv;
private errorMesage: string;
ngOnInit() {
this.errorMesage = "";
this._sdvDataService.getAdvForClient()
.subscribe(adv => {
this.loadAdverts = adv;
console.log ("here:" + this.loadAdverts)
}, error => {
this.errorMesage = <any>error;
});
}
}
I have a simple interface:
export interface IAdv {
Advertiser: string,
Source:string
}
and my html:
<div *ngIf="loadAdverts" >
<div class="row justify-content-center">
<div class="card" style="width: 20rem;">
<div class="card-body">
<h4 class="card-title">here: {{loadAdverts.Advertiser}}</h4>
<h6 class="card-subtitle mb-2 text-muted">{{loadAdverts.source}} </h6>
<p class="card-text">{{loadAdverts.source}}</p>
Card link
Another link
</div>
</div>
</div>
I can see the json displayed in the console from both console.log in the component and in the service but any data is displayed in the view.
I would appreciate any help?
Update: It seems the json coming from the server is a json string. So it is not being parsed in the observable. I had to use json.parse in the suscriber. How can I parse that json string to a json object automatically with the suscriber?
Your loadAdverts is a private variable and thus not accessible in the template.
Either make it public like this.
public loadAdverts:IAdv;
or use getters and setters.
private _loadAdverts:IAdv;
....
get loadAdverts(): IAdv {
return this._loadAdverts;
}
set loadAdverts(_ad: IAdv) {
this._loadAdverts = _ad;
}
....
As we can see, you are receiving an Object Job containing an array, so you should extract that array from the object:
getAdvForClient(): Observable<IAdv> {
return this._http.get(this._getAddsUrl)
.map((response: Response) => <IAdv>response.json().Job) // here!
.do(data => console.log('All:' + data))
.catch(this.handleError);
}
also, since you are getting an array, you would want to iterate that in your template:
<div *ngFor="let adv of loadAdverts">
<p>{{adv.Source}}</p>
<!-- more code here -->
</div>
also notice that this is case sensitive, in your template you used source as the property name instead of Source.