Search code examples
node.jsjsonangulartypescriptangular-httpclient

Angular 7 HttpClient get - can you access and process the return object?


I know this is a general question but I have exhausted google and tried many approaches.Any feedback is appreciated.

The HTTPClient is Angular 5+ so it returns an object created from the response JSON data. I get a massive JSON response from an endpoint I have no control over and I want to use about 20% of the response in my app and ignore the rest.

I am really trying hard to avoid using a series of templates or export objects or whatever and trying to force this massive untyped Observable into a typed object with hundreds of fields many being Arrays. All I need for the app is just a Array of very small objects with 3 fields per object. The 3 fields are all over within the JSON response and I want to map them to my object .map only seems to work when you are using the full response object and I can't find an example where .map does custom work besides in the case where you are mapping a few fields to 1 object and I am trying to map to an Array of my small objects.

UPDATED

Basically I want this service to return an object of Type DislayData to the module that subscribes to it but I get just an Object back. This is not what I ultimately need to do but if I can prove I can map the body of the response to my needed return type I can then start to break down the response body and return an Array of the Type I really need based on my silly DisplayData object. Thanks again!

export interface DislayData {

    body: any;
   
}

...
export class DataService {

  constructor(private http: HttpClient) { }
  /** GET data from the black box */
  getData(): Observable<DislayData> {

    return this.http.get<HttpResponse<any>>(searchUrl, { observe: 'response' })
      .pipe(
         map(res => {
           return res.body as DislayData;
        }
        tap(res => console.log(//do stuff with entire respoonse also)),
        catchError(err => this.handleError(err)));

  }

  private handleError(error: HttpErrorResponse) {
  ...


Solution

  • Do you know the structure of the answering object?

    If yes, you can do something like this:

    item$ = new BehaviorSubject<any>({});
    item = {
      foo: 'a',
      bar: 'b',
      iton: [1, 2, 3],
      boo: {
        far: 'c'
      }
    };
    
    logNewItem() {
        this.item$
          .pipe(
            map(response => {
              if (response.foo 
                  && response.iton
                  && response.iton.length >= 3 
                  && response.boo
                  && response.boo.far) {
                let newItem = {
                  foo: response.foo,
                  iton2: response.iton[2],
                  far: response.boo.far
                };
                console.log(newItem); // output: Object { foo: "a", iton2: 3, far: "c" }
              }
            })
          )
          .subscribe();
        this.item$.next(this.item);
      }
    

    Basically, you can simply make sure the properties exist, call them directly and map them to a better fitting object.

    I heavily recommend creating an interface for the object you're receiving and an interface or class for the object you're mapping to. In that case you can also write the code more compact like this:

    [...]
    map(response: MyAPIResponse => {
                let newItem = new NewItem(response);
                console.log(newItem); // output: Object { foo: "a", iton2: 3, far: "c" }
              }
            })
    [...]
    
    class NewItem {
    
    foo: string;
    iton2: string;
    far: string;
    
    constructor(apiResponse: MyAPIResponse) {
      //Validate parameter first
      this.foo = apiResponse.foo;
      this.iton2 = apiResponse.iton[2];
      this.far = apiResponse.boo.far;
    
    

    and make your code a lot more readable.