Getting a JSON and adding it to an array - json

I have following JSON file:
{
"fruites": [
{"id" :"f1", "name": "apple", "selected": "false"},
{"id": "f2" , "name":"orange", "selected": "false"}
]
}
Here is my JSON interface:
export interface FruitsType {
id: String;
name: String;
selected : String;
}
Not sure if this is a correct an interface.
I WANT TO USE THE NAME OF THE FRUITES AS VALUE FOR A CHECKBOX
To read this JSON I have following service:
getJSON (): Observable<JSON> {
return this.http.get<JSON>((this.configUrl))
}
}
In my component I have follwowing code to read the get the JSON file:
this.jsonService.getJSON().subscribe(response => {
console.log(response.fruites);
console.log(response.fruites[1].name);
console.log(response.fruites.length);
for (this.i = 0; this.i < response.fruites.length; this.i++) {
console.log("id" + response.fruites[this.i ].id);
console.log("name" + response.fruites[this.i].name);
console.log("selected" + response.fruites[this.i].selected);
}
})
in the browser I can see that it works, while in the consule where i am running the ng serve I see the following error:
src/app/componenets/home/home.component.ts(221,41): error TS2339: Property 'fruites' does not exist on type 'JSON'.
The other thing is that I cannot push this to an array, I use the follwoing code:
this.jsonArray.push(response.fruites[this.i].name )
AND
this.jsonArray.push(response.fruites)
AND
this.jsonArray.push(response)
All returs eithr undefined or nothing at all!
Please consult me on these.

I believe the payload you are getting can be easily done as:
this.jsonService.getJSON().subscribe(response => {
for(const i of response.fruites) { // Iterate over the list
console.log('Data set coming as - ', i);
console.log('ID - ', i.id);
console.log('Name - ', i.name);
console.log('Selected - ', i.selected);
}
array=[]; var item;
response.fruites.map((item) =>{ array.push(item.name)});
console.log('Array with name', array);`

Try it
response.json().fruites
or
response.data.fruites

in this post , I have posted the full answer of how I got everything done which also relates to this question I have asked.

Related

How to iterate over JSON returned by HttpClient

I have a simple Angular HttpClient, which is correctly returning JSON. I am attempting to cast the results to enforce type safety (not sure if this is correct).
But how do I actually access the returned JSON to copy it into an array?
The httpClient get() request is (and seems to be working fine):
public sendGetRequest(): Observable<Symbols[]> {
return this.httpClient.get<Symbols[]>(this.REST_API_SERVER);
}
The Symbols interface is
export interface Symbols {
code: string
desc: string
}
I have a component which calls the data service and is getting a response. However the code below returns an error when attempting to map the JSON into a string array
ERROR TypeError: syms.map is not a function
listOfOption: Array<{ value: string; label: string }> = []
this.dataService.sendGetRequest().subscribe((syms: Symbols[]) => {
console.log('return value ' + JSON.stringify(syms))
// console output shows the returned JSON and it looks correct
//this does not work, how do I copy the results to a string array??
this.listOfOption = syms.map(results => {
return {
value: results.code,
label: results.code,
}
})
})
The JSON data structure is:
{
"results": [
{
"code": "code1",
"desc": "Long description of code 1"
},
{
"code": "code2",
"desc": "Long description of code 2"
},
{
"code": "code3",
"desc": "Long description of code 3"
},
{
"code": "code4",
"desc": "Long description of code 4"
}
]
}
This is driving me crazy
Model a new interface called responseData to support response type.
export interface responseData{
results: Symbols[]
}
export interface Symbols {
code: string
desc: string
}
Update the same in service
public sendGetRequest(): Observable<responseData> {
return this.httpClient.get<responseData>(this.REST_API_SERVER);
}
You can now retrieve the results using array.map()
listOfOption: Array<{ value: string; label: string }> = []
this.dataService.sendGetRequest().subscribe((syms: responseData) => {
console.log('return value ' + syms)
this.listOfOption = syms.results.map(result => {
return {
value: result.code,
label: result.code,
}
})
})
The response data has an object root, but you're trying to parse it as an array root. I think the simplest solution would be something like this:
public sendGetRequest(): Observable<Symbols[]> {
return this.httpClient.get<{results: Symbols[]}>(this.REST_API_SERVER)
.pipe(pluck('results'));
}
Which specifies that the response data is an object with a field named results which holds an array of Symbols.
Alternatively you could also extract the response type to a separate definition:
interface ApiResponse {
results: Symbols[]
}
public sendGetRequest(): Observable<Symbols[]> {
return this.httpClient.get<ApiResponse>(this.REST_API_SERVER)
.pipe(pluck('results'));
}

Winston log format

i am using Winston ^3.0.0-rc6 as below :
var options = {
file: {
level: 'info',
filename: `${appRoot}/logs/app.log`,
handleExceptions: true,
json: true,
prettyPrint: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: true,
}
};
const jsonFormatter = (logEntry) => {
if (logEntry.type) {
const base = {
timestamp: new Date()
};
const json = Object.assign(base, logEntry);
logEntry[MESSAGE] = JSON.stringify(json);
} else {
logEntry = "";
}
return logEntry;
}
const logger = winston.createLogger({
format: winston.format(jsonFormatter)(),
transports: [
new winston.transports.File(options.file)
],
exceptionHandlers: [
new winston.transports.File(options.uncaughtExceptions)
]
});
my log output :
{"timestamp":"2018-06-10T07:41:03.387Z","type":"Authentication","status":"failed","level":"error","message":"Incorrect password"}
but i want them to be like :
{
"timestamp": "2018-06-10T07:41:03.387Z",
"type": "Authentication",
"status": "failed",
"level": "error",
"message": "Incorrect password"
}
i tried to play around with json : true , and prettyPrint but it did not do the trick .
Can any one help please
Thanks.
I noticed in your code that on the line
logEntry[MESSAGE] = JSON.stringify(json);
you're using JSON.stringify() which takes two more optional arguments
JSON.stringify(value[, replacer[, space]])
If you set space to the amount of spaces you'd like you'll get the output you're looking for. So change the initial line to be:
logEntry[MESSAGE] = JSON.stringify(json, null, 2); // or 4 ;)
(The replacer argument is null because we don't want to change the default behavior.)
This is deprecated: You can check the link here.
I tried to play around with json: true, and prettyPrint but it did not do the trick.
Simple code like this work for you:
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
If this does not work, let me know so that I can improvise.

How to solve Unexpected token p in JSON at position 3 using angular2 or typescript

When i go to save the survey content after editing, i get this error,
SyntaxError: Unexpected token p in JSON at position 3
at JSON.parse (<anonymous>)
Please anyone help me to solve this issue, I am hereby pasting my codes, please help.
ts code:
Surveypost = () => {
let token = this.auth.getAccessTokenId();
console.log(token)
let currentUser = this.auth.getCurrentUserData();
console.log(this.editor.text)
console.log(this.survey_val)
// let survey_json = JSON.parse(this.editor.text);
let survey_json:any;
try{
survey_json = JSON.parse(this.editor.text);
} catch(e) {
/*Handle the error scenario here*/
}
let survey_data = {
"value": survey_json,
};
console.log(survey_data)
this.AdminAPI
.createandSet(survey_data, token)
.subscribe(
survey => {
console.log(survey)
}, error => {
console.log(error);
}
);
}
I am getting the consoled output till, console.log(this.editor.text), then error comes.
The consoled output of console.log(this.editor.text) starts like this,
{
pages: [
{
name: "page1",
elements: [
{
type: "radiogroup",
name: "price",
title: "How long have you been a customer at {companyname}?",
isRequired: true,
choices: [
{
value: "less",
text: "0 - 3 months."
},
{
value: "medium",
text: "3 - 12 months."
},
{
value: "High",
text: "12 + months."
}
]
this.editor.text contains an invalid JSON.
When trying to parse that invalid JSON the error occurs. So in short terms, the following line is the one that crash: let survey_json = JSON.parse(this.editor.text);
Grab the output from the console.log(this.editor.text), run it trough a JSON validator/formatter like:
https://jsonformatter.curiousconcept.com/
And then you should be able to easily see why the error occurs, and why the program is not able to parse the JSON
EDIT FROM WHEN JSON HAS BEEN ADDED
AS you can see from the link mentioned above, the JSON is not valid, and that is the reason for the error message on the line: let survey_json = JSON.parse(this.editor.text);.
For instance a basic JSON should have the following structure:
{
"key" : "value",
"key2" : "value2"
}
You are also not ending the JSON correctly. I've formatted the JSON to a valid JSON here:
{
"pages":[
{
"name":"page1",
"elements":[
{
"type":"radiogroup",
"name":"price",
"title":"How long have you been a customer at {companyname}?",
"isRequired":true,
"choices":[
{
"value":"less",
"text":"0 - 3 months."
},
{
"value":"medium",
"text":"3 - 12 months."
},
{
"value":"High",
"text":"12 + months."
}
]
}
]
}
]
}
When you are trying to parse some text sent from a 3rd party source, it is a good idea to wrap the parse logic with a try catch block.
But do remember that this should be done only after fixing the trivial bugs in the remote source(that is, if you have access, of course).
replace,
let survey_json = JSON.parse(this.editor.text);
with,
let survey_json;
try{
survey_json = JSON.parse(this.editor.text);
} catch(e) {
/*Handle the error scenario here*/
/*Lets assign an empty object(or possibly a default value) instead*/
survey_json = {};
}

Angular reading data from json into textarea

I'm trying to read some test data from a local json file and output the data with correct formatting into a textarea. Right now though it just outputs [object Object]. How would I go about getting it so it outputs:
Id: theIdGoesHere
Title: theTitleGoesHere
step.service.ts The service used to call the json data
public getJson(): Observable<any>{
return this.http.get('/assets/jsonData/MyJson.json')
.map(response => response.json());
}
MyJson.json
{
"data":[
{
"id": 1,
"title":"Test1"
},
{
"id": 2,
"title":"Test2"
}
]
}
main.componenet.ts
private testVar: any;
test(){
this.stepService.getJson().subscribe(data => (this.testVar = data));
}
anothermethod(){
this.test();
this.mainStepText = this.testVar; //mainStepText binded to textarea with [(ngModel)]="mainStepText"
}
get mainStepText2() { //Rebinded this one
const text = [];
const { data } = this.testVar;
for (let item of this.testVar.data) {
Object.keys(item).forEach(key => {
text.push(key + ': ' + item[key]);
});
}
return text.join('\r\n'); // \r\n is the line break
}
You can use json pipe to format your object into a json string:
[(ngModel)]="mainStepText | json"
If you want to show a specific property of your object, you can access it in your template:
[(ngModel)]="mainStepText.data[0].title"
This will display "Test1" in your field.
You could loop through your json.data and through their keys to extract the text and values and generate the string you need for the text area.
const text = [];
for (let item of this.textVar.data) {
Object.keys(item).forEach(key => {
text.push(key + ': ' + item[key]);
});
}
return text.join('\r\n'); // \r\n is the line break
Here's the running code, I put it in app.ts: http://plnkr.co/edit/3AbQYQOW0MVBqO91X9qi?p=preview
Hope this is of help.

Typescript, JSON: Mapping nested array always returns empty

I am new to typescript and trying to parse a JSON from a GET request which looks like this (removed some data):
{
"currency_rate":1,
"data":[
{
"mapIdfrom":"oslo_no",
"refr":false,
"duration":{
"total":75300,
"return":0,
"departure":75300
},
"flyTo":"STR"
}
]
}
I am getting the "currency_rate" for example, but the "data"-array is empty.
The GET request looks like this (only relevant parts) :
[...]
api_url = 'https://api.skypicker.com/flights';
[...]
let body = {
flyFrom: 'OSL',
to: 'STR',
dateFrom: '01%252F04%252F2017',
dateTo: '20%2F04%2F2017',
daysInDestinationFrom: 15,
daysInDestinationTo: 20,
returnFrom: '01%2F04%2F2017',
returnTo: '20%2F04%2F2017',
typeFlight: 'oneway',
oneforcity: 0,
one_per_date: 0,
passengers: 1,
adults: 1,
children: 0,
infants: 0,
flyDays: '%5B0%2C1%2C2%2C3%2C4%2C5%2C6%5D',
onlyWorkingDays: 0,
directFlights: 0,
partner: 'picky',
partner_market: 'en',
v: 2,
xml: 0,
curr: 'EUR',
locale: 'en',
price_from: 1,
price_to: 10000,
dtimefrom: '00%3A00',
dtimeto: '00%3A00',
atimefrom: '00%3A00',
atimeto: '00%3A00',
returndtimefrom: '00%3A00',
returndtimeto: '00%3A00',
returnatimefrom: '00%3A00',
returnatimeto: '00%3A00',
stopoverfrom: '00%3A00',
stopoverto: '00%3A00',
booking_token: 'hashed%20data',
offset: 0,
limit: 30,
sort: 'price',
asc: 1
}
let bodyString = JSON.stringify(body)
return this.http.get(`${this.api_url}?${bodyString}`)
.map(res => <SkyPickerFlight>res.json());
The model "SkyPickerFlight" is defined like this:
import { SkyPickerFlightData } from '../models/skyPickerFlightData';
import { Observable } from 'rxjs/Rx';
export interface SkyPickerFlightI {
currency: string;
data: Observable<any[]>;
}
I have also tried replacing data: Observable<any[]> with data: Observable<SkyPickerFlightData[]>, the actual object, but also doesn't work.
Here you can get the full GET request:
https://api.skypicker.com/flights?flyFrom=OSL&to=STR&dateFrom=01%2F04%2F2017&dateTo=20%2F04%2F2017&daysInDestinationFrom=15&daysInDestinationTo=20&returnFrom=01%2F04%2F2017&returnTo=20%2F04%2F2017&typeFlight=oneway&oneforcity=0&one_per_date=0&passengers=1&adults=1&children=0&infants=0&flyDays=%5B0%2C1%2C2%2C3%2C4%2C5%2C6%5D&onlyWorkingDays=0&onlyWeekends=0&directFlights=0&partner=picky&partner_market=en&v=2&xml=0&curr=EUR&locale=en&price_from=1&price_to=10000&dtimefrom=00%3A00&dtimeto=00%3A00&atimefrom=00%3A00&atimeto=00%3A00&returndtimefrom=00%3A00&returndtimeto=00%3A00&returnatimefrom=00%3A00&returnatimeto=00%3A00&stopoverfrom=00%3A00&stopoverto=00%3A00&booking_token=hashed%20data&offset=0&limit=30&sort=price&asc=1
I am still looking into it but it looks like the GET request is a bit funky using this.http.get(${this.api_url}?${bodyString}) actually returns:
{"connections":[],"currency":"EUR","del":0,"time":1,"search_params":{"to_type":"anywhere","flyFrom_type":"anywhere","seats":{"infants":0,"passengers":1,"adults":1,"children":0}},"ref_tasks":{},"currency_rate":1.0,"data":[],"refresh":[]}
A different result than the GET request above. Not sure if I was clear. But trying the GET request like this (I will spare you with the long definition of the URLSearchParams) ends in a Bad Gateway error:
return this.http.get(this.api_url, {search: params})
.map(res => res)
---- EDIT -----
It worked after I copy-pasted the entire URL in:
return this.http.get(<URL PASTED HERE>)
.map(res => res)
Would still like to know how to pass the parameters in a clean way rather than pasting the entire URL in there.
A section of your json response would not be an Observable.
Try:
export interface SkyPickerFlightI {
currency: string;
data: any[];
}
You will get an Observable<SkyPickerFlightI> from http which would contain both currency_rate and data
I did not understand what are you trying to achieve by data: Observable<any[]>;. As #suraj said, "A section of your json response would not be an Observable".
As for the answer, I think you do not need to typecast the response into a typical Interface. A simple .map(res => res.json()); would also work. I am assuming you need it like this, but, just saying to make it easier.
Not sure if problem exists there? So, you can do this and check if the data is coming to your GET :
return Observable.create(observer => {
this.http.get(`${this.api_url}?${bodyString}`)
.map(res => res.json())
.subscribe((data) => {
console.log("Data : ", data);
observer.next(data);
},
(err) => {
console.log("Error : ", err);
observer.error(err);
});
});
Check if above logs the necessary data. If it does then check again by typecasting as you were doing in your code.
Now, here you are returning a new Observable to calling method. So, you will have to subscribe() in calling method as well.
The problem was the GET request. Using URLSearchParams/RequestOptions didnt work for some reason. Kept getting a 'BAD GATEWAY' error. So I passed the url directly in the http request like so:
this.http.get('https://api.skypicker.com/flights?' + bodyStringSerialized)
Using the below serialize function (another version of this function I found messed with the values of the param-values, so I removed the encoding). I used it likt this 'serialized(json, '')':
serialize(obj, prefix) {
var str = [], p;
for(p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push((v !== null && typeof v === "object") ?
this.serialize(v, k) :
k + "=" + v);
}
}
return str.join("&");
}
Thanks for the help!