Observable is always undefined when transform the value using map - json

I'm trying to understand why when I transform the observable it comes up undefined in the console log even though I know it has values assigned to it.
Http Request
getLibraryCardPeople(bookName: String): Observable<people[]> {
return this.http.get<LibraryCard>(url).pipe(map(results => results.people));
}
JSON response
book : "LOTR"
people : [
{"name" : "joe", "age" : 20 , "Location": [...]},
{"name" : "sarah", "age" : 16 , "Location": [...]}
]
When I execute the function and try and observe the people array is always undefined in the console log. However, If I don't map, I can see the entire JSON Response is defined.

You need to subscribe to the httpClient. First subscribe will activate the http call so to say.
getLibraryCardPeople(bookName: String): Observable<people[]> {
return this.http.get<LibraryCard>(url);
}
Then in your component:
this.myService.getLibraryCardPeople.subscribe(data => {
data.pipe(map(results => results.people));
})
This is the normal way to use HttpClient. What you can do, too, is to use toPromise from RxJS. Read all about here. A example:
this.http.get<LibraryCard>(url).toPromise()
.then(res => console.log(res))
.catch(err => { console.log ('error');

Related

Firebase Request simplification and error fixing

I have a bunch of forms that input data into my firebase database using a express API and cloud functions.
I have one main issue - I'm getting a error on trying to test my API when inputting the form data.
The secondary issue is more, is there a cleaner way to take the inputted form data to the firebase than how I am currently doing it.
This is the code to create a new workflow (which is the data outputed from the forms)
(this is the required code from the route file)
const {getAllWorkflows,
postOneWorkflow} = require('./handlers/workflow');
// Workflow Routes
app.get('/Workflows', getAllWorkflows);
app.post('/Workflow', postOneWorkflow);
And this is the request code from a handler file
exports.postOneWorkflow = (req, res) => {
const newWorkflow = {
completed: req.body.completed,
currentStep: req.body.currentStep,
createdAt: new Date().toISOString(),
Reason: req.body.Reason,
breach: req.body.breach,
cauInd: req.body.cauInd,
cauOth: req.body.cauOth,
cauWea: req.body.cauWea,
claimEoT: req.body.claimEoT,
dateAware: req.body.dateAware,
dateEoTClaim: req.body.dateEoTClaim,
daysClaimed: req.body.daysClaimed,
dec: req.body.dec,
delayRespon: req.body.delayRespon,
descB: req.body.descB,
descCau: req.body.descCau,
descExt: req.body.descExt,
event: req.body.event,
eviCause: req.body.eviCause,
eviExtent: req.body.eviExtent,
ifGranDay: req.body.ifGranDay,
notice: req.body.notice,
proMitPro: req.body.proMitPro,
proResPro: req.body.proResPro,
recWri: req.body.recWri,
stepsMit: req.body.stepsMit,
stepsPre: req.body.stepsPre
};
db.collection("Workflow")
.add(newWorkflow)
.then(doc => {
const resWorkflow = newWorkflow;
resWorkflow.WorkflowId = doc.id;
res.json(resWorkflow);
})
.catch(err => {
res.status(500).json({ error: "something went wrong" });
console.error(err);
});
};
I'm currently receiving an error of
SyntaxError: Unexpected token c in JSON at position 10
when inputting json using postman to the workflow post route,
{
completed: "False",
currentStep: 1,
claimEoT: "True",
event: "True",
notice: "True",
recWri: "True",
dateEotClaim: "",
dateAware: "",
eviCause: "",
descCau : "",
eviExtent : "True",
descExt : "",
daysClaimed : 5,
delayRespon : "True",
proResPro : 1,
stepsPre : "True",
proPrePro : 1,
stepsMit: "True",
proMitPro : 10 ,
breach : "True",
descB : "describe",
cauInd : "True",
cauWea : "True",
cauOth : "True",
dec : "True",
ifGranDay : 5,
Reason : "I AM THE SENATE"
}
Not 100% sure why as it seems like my formatting is fine?
With creating the query - I wonder if there is a more efficient way of doing this other than writing an ungodly amount of code for the queries.
The point is I need to be able to query the different collections and edit them, but I feel like a query that just took in what it was told, and sent it through to this database, without having to specify the specific "completed", or "Reason",would be ideal.
Your postman JSON is invalid. The keys are also supposed to be enclosed in quotes.
{
"completed": "False",
"currentStep": 1,
...
}
You can just create the newWorkflow object from req.body!
const newWorkflow = req.body;
newWorkflow.createdAt = new Date().toISOString();

Retrieve values from JSON response, and create a drop-down

I'm trying to get each of of the values inside my JSON file but when I run my API I get [Object Object] instead of what is inside the JSON.
This is my API request:
getAllvalues(): Observable<string[]> {
return this.http
.get<string[]>(this.Url + 'api');
}
my component.ts
this.ddvService.getAllvalues()
.subscribe(response => {
this.slots = response;
console.log (this.slots)
});
Example of my JSON response:
[
{
"AB": "http:"
},
{
"DE": "http:"
},
{
"CE": "http:"
},
{
"HI": "http:"
}
]
How can I get the value inside the JSON, and create a dropdown box with each of them?
Your example JSON is a pretty bad example: each object in the array in the JSON should have at least somewhat matching key names. In your case, the keys are "AB", "DE", "CE", "HI" - all different, which is quite uncommon in real-life. A more realistic JSON response would have matching key names, e.g.:
[
{
"id": "1",
"description": "Some description"
},
{
"id": "2",
"description": "Another description"
}
]
Now to answer your questions:
You are getting [Object Object] because you are trying to use an entire object as a literal value. Instead, you should access the individual keys/values of an object. For example: console.log(slots[0].id) - this should output 1.
Also, as indicated in the comments, replace Observable<string[]> with Observable<any[]> and get<string[]> with get<any[]>.
To create a drop-down in Angular, in your component template you can try this, assuming your slots value is the JSON above:
<select *ngIf="slots" name="slots">
<option *ngFor="let slot of slots" value="slot.id">{{ slot.description }}</option>
</select>
Also, to print the entire object to console in a readable form, instead of just console.log(this.slots);, you can try console.log(JSON.stringify(this.slots));
As mentioned in the comments above it is not ideal to have json like you have, my assumption is you might want to log keys instead of values, since value is same for all the objects in array. In that case you might want to try something like this.
1. Add any[] instead string[].
2.Add nested for loop to console.log your object array.
getAllvalues(): Observable<string[]> {
return this.http
.get<any[]>(this.Url + 'api');
}
this.ddvService.getAllvalues()
.subscribe(response => {
this.slots = response;
for(let i in this.slots)
{
let currentObj = this.slots[i]; // example of first in array { AB : "http:"}
for ( let z in currentObj )
{
if(currentObj[z]=== "http:") // we are trying to find key instead value
{
console.log(z); // it will log AB, DE, CE, HI ..
}
}
}
});

TypeScript / Angular 2 creating a dynamic object deserializer

So I am coming from a background of C# where I can do things in a dynamic and reflective way and I am trying to apply that to a TypeScript class I am working on writing.
Some background, I am converting an application to a web app and the backend developer doesn't want to change the backend at all to accommodate Json very well. So he is going to be sending me back Json that looks like so:
{
Columns: [
{
"ColumnName": "ClientPK",
"Label": "Client",
"DataType": "int",
"Length": 0,
"AllowNull": true,
"Format": "",
"IsReadOnly": true,
"IsDateOnly": null
}
],
Rows:[
0
]
}
I am looking to write an Angular class that extends Response that will have a special method called JsonMinimal which will understand this data and return an object for me.
import { Response } from "#angular/http";
export class ServerSource
{
SourceName: string;
MoreItems: boolean;
Error: string;
ExtendedProperties: ExtendedProperty[];
Columns: Column[];
}
export class ServerSourceResponse extends Response
{
JsonMinimal() : any
{
return null; //Something that will be a blank any type that when returned I can perform `object as FinalObject` syntax
}
}
I know StackOverflow isn't for asking for complete solutions to problems so I am only asking what is one example taking this example data and creating a dynamic response that TypeScript isn't going to yell at me for. I don't know what to do here, this developer has thousands of server-side methods and all of them return strings, in the form of a JSON or XML output. I am basically looking for a way to take his column data and combine it with the proper row data and then have a bigger object that holds a bunch of these combined object.
A usage case here after that data has been mapped to a basic object would be something like this.
Example:
var data = result.JsonMinimal() as LoginResponse; <-- Which will map to this object correctly if all the data is there in a base object.
var pk = data.ClientPK.Value;
I'm not exactly sure I understand, but you may want to try a simple approach first. Angular's http get method returns an observable that can automatically map the response to an object or an array of objects. It is also powerful enough to perform some custom mapping/transformation. You may want to look at that first.
Here is an example:
getProducts(): Observable<IProduct[]> {
return this._http.get(this._productUrl)
.map((response: Response) => <IProduct[]> response.json())
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
Here I'm mapping a json response to an array of Product objects I've defined with an IProduct interface. Since this is just a "lambda" type function, I could add any amount of code here to transform data.

Laravel 5.4 won't validate JSON

I'm using Laravel 5.4 and trying to validate JSON in my POST request however the validator fails stating that the JSON isn't valid, even though it is. I'm assuming I'm not understanding the validation rules correctly and my implementation is wrong, rather than a bug or something else.
I have a simple POST endpoint which has both the Accept and Content-Type headers set to application/json.
In my POST request (testing using Postman) I'm supplying RAW data.
{
"only_this_key": { "one": "two" }
}
In my controller method I have the following:
// I'm using intersect to remove any other parameters that may have been supplied as this endpoint only requires one
$requestData = $request->intersect(['only_this_key']);
$messages = [
'only_this_key.required' => 'The :attribute is required',
'only_this_key.json' => 'The :attribute field must be valid JSON',
];
$validator = \Validator::make($requestData, [
'only_this_key' => 'required|json',
], $messages);
if ($validator->fails()) {
return new APIErrorValidationResponse($request, $validator);
}
return response()->json(['all good' => 'here']);
The error I get back is The inventory field must be valid JSON even though it is!
Passing in the raw data using Postman
{
"only-this-key": {
"item-one": "one",
"item-two": "two",
"item-three": "three"
},
"not": "wanted"
}
When I use dd($request->all()); within the method
array:2 [
"what-i-want" => array:3 [
"item-one" => "one"
"item-two" => "two"
"item-three" => "three"
]
"not" => "wanted"
]
The problem is with how Laravel is interpreting the raw data in the request. If you run dd($request->all()) in your controller you will see this output:
array:1 [
"{"only_this_key":{"one":"two"}}" => ""
]
Your entire JSON string is getting set as a key with a value of an empty string. If you absolutely must send it as raw data, then you're going to have to grab that key value and save it to an array with the key that you want. This should work (instead of the intersect line).
$requestData = ['only_this_key' => key($request->all())];
Alternatively, you can just send the body as x-www-form-urlencoded with your entire JSON string as the only value for one key.

Parsing JSON file into logstash

Hi I am trying to send a json file with multiple objects to elasticsearch with the logstash so I can display the data using kibana. I have researched this extensively and simply cannot understand how to make the data formatted correctly to be used in kibana.
I have tried to use different filters such as: json, date, and grok
The issue is probably how I'm going about using these filters as I can't understand it's setup all to well.
Here is a sample line of the input json file:
{"time":"2015-09-20;12:13:24","bug_code":"tr","stacktrace":"543534"},
I want to use this format for displaying the data in kibana and sorting many objects according to their "time"
this following is what my current filter section is:
filter {
date {
match => ["time", "YYYY-MM-dd;HH:mm:ss Z" ]
timezone => "America/New_York"
locale => "en"
target => "#timestamp"
}
grok {
match => ["time", "%{TIMESTAMP_ISO8601:timestamp}"]
}
}
At this point I know the grok is wrong because I get "_grokparsefailure"
but how can I figure out the correct way to use grok or is there a simple way to sort the data using the given timestamp and not the processed timestamp given when sending the data through.
here is what the output currently shows:
"message" => "{\"time\":\"2015-09-20;12:13:24\",\"bug_code\":\"tr\",\"stacktrace\":\"543534\"},\r",
"#version" => "1",
"#timestamp" => "2015-11-23T09:54:50:274Z",
"host" => "<my_computer>",
"path" => "<path_to_.json>",
"type" => "json",
"tags" => [
[0] "_grokparsefailure"
any advice would be very much appreciated
You're almost there, I could get it working with a few tweaks.
First, you need to add the json{} filter in the first position. Then you need to change the date pattern to YYYY-MM-dd;HH:mm:ss and finally you can remove the grok filter at the end. You filter configuration would look like this:
filter {
json {
source => "message"
}
date {
match => ["time", "YYYY-MM-dd;HH:mm:ss" ]
timezone => "America/New_York"
locale => "en"
target => "#timestamp"
}
}
The parsed event for your sample JSON line would then look like this:
{
"message" => "{\"time\":\"2015-09-20;12:13:24\",\"bug_code\":\"tr\",\"stacktrace\":\"543534\"}",
"#version" => "1",
"#timestamp" => "2015-09-20T16:13:24.000Z",
"host" => "iMac.local",
"time" => "2015-09-20;12:13:24",
"bug_code" => "tr",
"stacktrace" => "543534"
}