I am new to angular little confused,
When I am calling the Rest API, Getting the JSON response
But I need to store that JSON response into a (Map<string, string>),
cloud please help to fix this.
Edit 1:
On calling api/user/id getting below json response
{
"firstname":"test",
"lastname":"testlastname",
"email":"test#test.com",
"username":"ufk",
"password":"qweasd",
"phone":"123456789"
}
Service.ts:
public getJSONResponse(): Observable<Map> {
return this.http.get<Map>('api's end point');
}
Model:
export class Map{//sample Model
firstname : string
lastname : string
email : string
username : string
password : string
phone : string
}
Used below code to solve, JSON response directly sending to a map
return this.http.get('/api/user/' + ID, options)
.map((response: Response) => {
return response.json() as User;
}).toPromise().then(x => {
this.user= x;
})
Related
I have created an API using laravel to check if an email existed in database or not.
/**
*
* #param string $email
*/
public function checkUserEmail($email)
{
$userCount = User::where('email', $email);
if($userCount->count()){
return response()->json("true");
}else{
return response()->json("false");
}
}
I have tested this API in postman and it works as expected
Test using Postman
But, when I have use it in frontend it return an object not string!!
Frontend:
checkUserEmail(email : string){
return this.http.get<any>("http://127.0.0.1:8000/api/auth/user-email/"+email);
}
Browser console
In order to get the returned string using HttpClient in Angular you have to subscribe to Observable that returns.
Or you can do the async way using firstValueFrom from RxJS. Notice that response is in string because contains quotes ("false"), is better to just send true or false as boolean.
Here's the example:
public checkUserEmail(email: string): Observable<string> {
return this.http.get("http://127.0.0.1:8000/api/auth/user-email/" + email)
.pipe(
map((response: string) => response as string),
catchError( (errorObject) => {
return throwError(() => errorObject);
}
)
);
}
And now you can call this function subscribing or using async way:
Subscribe way (don't forget to unsubscribe):
checkIfEmailIsInDatabase(email: string): void {
this.checkUserEmail("some#email.com").subscribe(
(response: string) => {
// Do your stuff here, like setting variables or whatever
console.log("Response: ", response);
}
)
}
Async way:
async checkIfEmailIsInDatabase(email: string): Promise<void> {
let responseFromServer: string = await firstValueFrom(this.checkUserEmail(email));
console.log("Response from server: ", responseFromServer);
}
Hope it helps.
In Angular the return type of the httpClient's methods are Observables. So in your client code you have to subscribe to the observable. I also suggest so change "any" to string
Controller code:
[Route("api/[controller]")]
[ApiController]
public class AjaxController : ControllerBase
{
ApplicationDbContext dbContext = null;
public AjaxController(ApplicationDbContext ctx)
{
dbContext = ctx;
}
[HttpGet]
[Route("GetString")]
public string GetString()
{
return "Hello World";
}
[HttpGet]
[Route("GetCategories")]
public Category[] GetCategories()
{
return dbContext.Categories.ToArray();
}
}
Angular code:
http.get<string>(baseUrl + 'api/ajax/GetString').subscribe(result => {
console.log(result);
}, error => console.error(error));
While Angular can parse without error the GetCategories endpoint, it cannot parse the much simpler GetString. Why? The error in the console is:
error: SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
text: "Hello World"
I tried wit Postman and the response is just fine, see screenshot:
The issue is your response from GetString is returning just a string of value Hello World as shown by the screenshot from Postman. The GetCategories endpoint must be returning valid JSON if you are getting a valid response.
By default Angular assumes the response type of a HttpRequest to be of type json.
To fix this, specify as the second parameter to http.get() the responseType expected from the server which in your case for the GetString endpoint will be 'text'. So your http.get() call should look like the following:
http.get<string>(baseUrl + 'api/ajax/GetString', { responseType: 'text' }).subscribe(result => {
console.log(result);
}, error => console.error(error));
If your intention was to return valid JSON from GetString then you need to format the response from your server as appropriate.
See the Angular documentation on HttpRequest - responseType. I've included a copy below.
responseType: 'arraybuffer' | 'blob' | 'json' | 'text'
The expected response type of the server.
This is used to parse the response appropriately before returning it to the requestee.
I am using angular 4.2.6 for my application. I have a service like this
checkStaff(email: any) {
return this._http.post(this.url + "/Impsapi/getStaff", JSON.stringify(email)).map(
(resp) => resp
)
}
checkStaff(email:any){
return
this._http.post(this.url+"/Impsapi/getStaff",JSON.stringify(email)).map(
(resp)=> resp
)
}
this.loginServ.checkStaff(this.user)
.subscribe(
userData => {
this._return = userData;
console.log(this._return);
}
);
The Server returns JSON as response. but when i log the output, i get the below
logged response
please I need to consume the data in the body of the response. I have not been able convert the ._body to a proper json and use for the app. please help
The response data are in JSON string form. The app must parse that string into JavaScript objects by calling res.json().
return this._http.post(this.url + "/Impsapi/getStaff", JSON.stringify(email)).map(
(resp) => resp.json()
)
Update
try following code snippet
checkStaff(email: any) {
return this._http.post(this.url + "/Impsapi/getStaff", JSON.stringify(email))
.map(res => {return res.json()})
}
Try this:
this.loginServ.checkStaff(this.user)
.subscribe(
userData => {
this._return = userData.json();
console.log(this._return);
}
);
I mean your checkStaff:
checkStaff(email: any): Observable<Response> {
return this._http.post(this.url + "/Impsapi/getStaff", JSON.stringify(email));
}
export classMyResp
{
id: string;
/*so on...*/
}
This will give you the body of response If there is any.
I got my problem solved. My PHP is hosted on wampserver. In a way invalid JSON is always returned when i make call to the server. I had to use the ob_clean() function and everything is fine.
So I'm getting the following JSON structure from my asp.net core api:
{
"contentType": null,
"serializerSettings": null,
"statusCode": null,
"value": {
"productName": "Test",
"shortDescription": "Test 123",
"imageUri": "https://bla.com/bla",
"productCode": null,
"continuationToken": null
}
}
I have the following typescript function that invokes the API to get the above response:
public externalProduct: ProductVM;
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get("api/product?productCode=" + code)
.map((data: ProductVM) => {
this.externalProduct = data; //not working...
console.log("DATA: " + data);
console.log("DATA: " + data['value']);
return data;
});
}
ProductVM:
export interface ProductVM {
productName: string;
shortDescription: string;
imageUri: string;
productCode: string;
continuationToken: string;
}
My problem is that I can't deserialize it to ProductVM. The console logs just produce [object Object]
How can I actually map the contents of the value in my json response to a ProductVM object?
Is it wrong to say that data is a ProductVM in the map function? I have tried lots of different combinations but I cannot get it to work!
I'm unsure whether I can somehow automatically tell angular to map the value array in the json response to a ProductVM object or if I should provide a constructor to the ProductVM class (it's an interface right now), and extract the specific values in the json manually?
The data object in the map method chained to http is considered a Object typed object. This type does not have the value member that you need to access and therefore, the type checker is not happy with it.
Objects that are typed (that are not any) can only be assigned to untyped objects or objects of the exact same type. Here, your data is of type Object and cannot be assigned to another object of type ProductVM.
One solution to bypass type checking is to cast your data object to a any untyped object. This will allow access to any method or member just like plain old Javascript.
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get("api/product?productCode=" + code)
.map((data: any) => this.externalProduct = data.value);
}
Another solution is to change your API so that data can deliver its content with data.json(). That way, you won't have to bypass type checking since the json() method returns an untyped value.
Be carefull though as your any object wil not have methods of the ProductVM if you ever add them in the future. You will need to manually create an instance with new ProductVM() and Object.assign on it to gain access to the methods.
From angular documentation: Typechecking http response
You have to set the type of returned data when using new httpClient ( since angular 4.3 ) => this.http.get<ProductVM>(...
public externalProduct: ProductVM;
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get<ProductVM>("api/product?productCode=" + code)
.map((data: ProductVM) => {
this.externalProduct = data; // should be allowed by typescript now
return data;
});
}
thus typescript should leave you in peace
Have you tried to replace
this.externalProduct = data;
with
this.externalProduct = data.json();
Hope it helps
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get("api/product?productCode=" + code)
.map(data => {
this.externalProduct = <ProductVM>data;
console.log("DATA: " + this.externalProduct);
return data;
});
}
So, first we convert the response into a JSON.
I store it into response just to make it cleaner. Then, we have to navigate to value, because in your data value is the object that corresponds to ProductVM.
I would do it like this though:
Service
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get(`api/product?productCode=${code}`)
.map(data => <ProductVM>data)
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
Component
this.subscription = this.myService.getProductExternal(code).subscribe(
product => this.externalProduct = product,
error => console.warn(error)
);
I used this approach in a client which uses the method
HttpClient.get<GENERIC>(...).
Now it is working. Anyway, I do not understand, why I do not receive a type of T back from the http client, if I don't use the solution provided in the answer above.
Here is the client:
// get
get<T>(url: string, params?: [{key: string, value: string}]): Observable<T> {
var requestParams = new HttpParams()
if (params != undefined) {
for (var kvp of params) {
params.push(kvp);
}
}
return this.httpClient.get<T>(url, {
observe: 'body',
headers: this.authHeaders,
params: requestParams
}).pipe(
map(
res => <T>res
)
);
}
I have an issue while I try to cast a json response to object, all the properties of my object are string is that normal ?
Here is my ajax request :
public getSingle = (keys: any[]): Observable<Badge> => {
return this._http.get(this.actionUrl + this.getKeysUrl(keys))
.map((response: Response) => response.json() as Badge )
.catch(this.handleError);
}
Here is my badge model :
export interface Badge {
badgeNumber: number;
authorizationLevel: number;
endOfValidity: Date;
}
And here is where I call the service function and I'm facing the issue :
this._badgeService.getSingle(this.ids).subscribe(
(badge: Badge) => {
console.log(typeof(badge.endOfValidity)); // <-- returning string and not Date
},
error => console.log(error);
});
Thats kinda tricky to explain:
Date is a class, this means that values of type Date need to be created through a constructor call. In other words, create a class instance with new Date(...).
The Response.json method will only return an object in JSON format, and such doesnt contain an instance of any class, only maps of key:property.
So what you need to do, is to manually convert the value returned from .json() to a Base object. This can be done as follows:
public getSingle = (keys: any[]): Observable<Badge> => {
return this._http.get(this.actionUrl + this.getKeysUrl(keys))
.map(r => r.json())
.map(v => <Badge>{
badgeNumber: v.badgeNumber,
authorizationLevel: v.authorizationLevel,
endOfValidity: new Date(v.endOfValidity)
// preferably this string should be in ISO-8601 format
})
//the mapping step can be done in other ways most likely
.catch(this.handleError);
}