1

How can I have HttpClient return the data as a JSON Object?

Angular docs say that HttpClient should parse returned JSON data as an object. In my project, it only returns the data as a string.

If I use JSON.parse, I can turn the data into an object and get the data that way and it works. But from what I've seen in articles, that is not good practice. Also, most articles/tutorials only use interfaces.

I've created an interface and tried using it, but it doesn't work. I've read so many posts and articles, but they all say that HttpClient should return an object by default.

Here is the code from my service. The first function gets the user's coordinates, and the second function uses the coordinates to request data from the api.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, pipe } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from '../../../environments/environment';
import { Aqi } from './aqi';

@Injectable({
  providedIn: 'root'
})
export class AqiService {
  aqiUrlCoords = `${environment.apiUri}airvisual/geo/`;

  constructor(private http: HttpClient) {}

  getLocation(): Observable<any> {
    return Observable.create(observer => {
      if(window.navigator && window.navigator.geolocation) {
        window.navigator.geolocation.getCurrentPosition(
          (position) => {
            observer.next(position);
            observer.complete();
          },
          (error) => observer.error(error)
        );
      } else {
        observer.error('Unsupported Browser');
      }
    });
  }

  getGeoLocationAqi(lat, long): Observable<any> {
    return this.http.get<any>(this.aqiUrlCoords, { params: {
      lat: lat,
      long: long
    }});
  }

}

to get the getGeoLocationAqi() function to work, I have to use this...

getGeoLocationAqi(lat, long): Observable<any> {
    return this.http.get<any>(this.aqiUrlCoords, { params: {
      lat: lat,
      long: long
    }}).pipe(
      map(res => {
        return JSON.parse(res);
      })
    );
  }

Here is the component that uses the service and data. typeof always prints string.

import { Component, OnInit } from '@angular/core';
import { AqiService } from '../services/aqi/aqi.service';
import { Aqi } from './aqi';

export class GeoComponent implements OnInit {
  aqi: any;
  errorMessage: string;

  constructor(private aqiService: AqiService) {}

  ngOnInit() {
    this.getCurrentCoordinatesAqi();
  }

  getCurrentCoordinatesAqi() {
    this.aqiService.getLocation().subscribe(pos => {
      let lat = pos.coords.latitude.toString();
      let long = pos.coords.longitude.toString();
      this.aqiService.getGeoLocationAqi(lat, long).subscribe((res) => {
        this.aqi = res;
        console.log(res);
        console.log(typeof res);
      });
    }, (err) => {
      this.errorMessage = err;
    });
  }
}

Here is the interface I have made.

export interface Aqi {
  status: string,
    data: {
        city: string,
        state: string,
        country: string,
        location: {
            type: string,
            coordinates: [
              number,
              number
            ]
        },
        current: {
            weather: {
                ts: string,
                hu: number,
                ic: string,
                pr: number,
                tp: number,
                wd: number,
                ws: number
            },
            pollution: {
                ts: string,
                aqius: number,
                mainus: string,
                aqicn: number,
                maincn: string
            }
        }
    }
}

Here is what is returned from the api by using postman.

{
    "status": "success",
    "data": {
        "city": "Hanoi",
        "state": "Hanoi",
        "country": "Vietnam",
        "location": {
            "type": "Point",
            "coordinates": [
                105.81881,
                21.021938
            ]
        },
        "current": {
            "weather": {
                "ts": "2019-04-30T16:00:00.000Z",
                "hu": 100,
                "ic": "04n",
                "pr": 1010,
                "tp": 25,
                "wd": 70,
                "ws": 2.6
            },
            "pollution": {
                "ts": "2019-04-30T15:00:00.000Z",
                "aqius": 151,
                "mainus": "p2",
                "aqicn": 76,
                "maincn": "p2"
            }
        }
    }
}

I expect typeof to print object, but it always prints string unless I use JSON.parse(). When I use the interface, I still get the string. Any help is appreciated!

1
  • 2
    Do you really need to post that much codes? Commented Dec 4, 2019 at 3:20

1 Answer 1

5

You don't need to parse the response, the http client return objects by default as long as your endpoint is returning JSON objects and the content type is application/json. Your endpoint is probably returning some text content type.

Sign up to request clarification or add additional context in comments.

2 Comments

That worked! Thank you so much! My api was returning a string. I used JSON.parse on the backend to make it send an object. Now I can use my interface on the front end.
You should probably use a rest Framework for your api like Nest.js or Express.js rather than rolling your own.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.