Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typescript load json data from url into arrays

I have json data coming in from a URL. The data looks like this:

[
  {"id":1,"symbol":"SP-500","date":"1927-12-30T07:00:00.000+00:00","open":17.66,"high":17.66,"low":17.66,"close":17.66,"volume":0},
  {"id":2,"symbol":"SP-500","date":"1928-01-03T07:00:00.000+00:00","open":17.76,"high":17.76,"low":17.76,"close":17.76,"volume":0}
]

The code to retrieve it is in quote.service.ts and looks like this:

  getQuotesList(): Observable<any> {
    return this.http.get(`${this.baseUrl}`);
  }

Here is the whole class:

        import { Injectable } from '@angular/core';
        import { HttpClient } from '@angular/common/http';
        import { Observable, Subject } from 'rxjs';
        import { of } from 'rxjs';
        import 'rxjs/add/operator/map'
        import 'rxjs/operator/filter';
        import { Quote } from "./quote";
        
        @Injectable({
          providedIn: 'root'
        })
        export class QuoteService {
        
          private baseUrl = 'http://localhost:8080/springboot-crud-rest/api/v1/quotes';
        
          constructor(private http: HttpClient) { }
        
          getQuote(id: number): Observable<any> {
            return this.http.get(`${this.baseUrl}/${id}`);
          }
        
          createQuote(quote: Object): Observable<Object> {
            return this.http.post(`${this.baseUrl}`, quote);
          }
        
          updateQuote(id: number, value: any): Observable<Object> {
            return this.http.put(`${this.baseUrl}/${id}`, value);
          }
        
          deleteQuote(id: number): Observable<any> {
            return this.http.delete(`${this.baseUrl}/${id}`, { responseType: 'text' });
          }
        
          //getQuotesList(): Observable<any> {
          //  return this.http.get(`${this.baseUrl}`);
          //}
    
    getQuotesList(): Observable<[string[], string[]]> {
      // replace of(data) to this.http.get(this.baseUrl)
      return of(data).pipe(
        map((quotes) => {
          return quotes.reduce((acc, curr) => {
            acc[0].push(curr.date.substr(0, 10));
            acc[1].push(curr.open);
            return acc;
          }, [[], []]);
        }),
      )
    }
}

The data is then sent on to quote-list.component.ts which successfully loads it into the quotes array like this:

export class QuoteListComponent implements OnInit {
  quotes: Observable<Quote[]>;

It then passes quotes on to quote-list.component.html and builds a table using the following code:

<tr *ngFor="let quote of quotes | async">
  <td>{{quote.symbol}}</td>
  <td>{{quote.date}}</td>
  <td>{{quote.open}}</td>
  <td>{{quote.high}}</td>
  <td>{{quote.low}}</td>
  <td>{{quote.close}}</td>
  <td>{{quote.volume}}</td>
  <td><button (click)="deleteQuote(quote.id)" class="btn btn-danger">Delete</button>
      <button (click)="quoteDetails(quote.id)" class="btn btn-info" style="margin-left: 10px">Details</button>
  </td>
</tr>

The table looks nice and all the data is there.

Now I want to load it into a separate array for each value, like this:

[1927-12-30,1928-01-03]
[17.66,17.76]

etc.

And then I want to make those arrays available to a javascript charting program which will plot the data. That plotting code requires a separate array for each value.

I thought that if I modified quote.service.ts to look something like

  getQuotesList(): Observable<any> {
    let quotes = this.http.get(`${this.baseUrl}`);
    let opens = quotes.map(theOpen => open);
    console.log("opens.length=" + opens.length);
    opens.forEach(function(item,index,array) {
        console.log(item,index);
        })
    return quotes;
  }

But get the error:

ERROR in quote.service.ts:38:23 - error TS2339: Property 'map' does not exist on type 'Observable<Object>'.

38    let opens = quotes.map(theOpen => open);

So I changed getQuotesList(): Observable<any> to getQuotesList(): Observable<Quote[]>

But got the following error:

ERROR in quote.service.ts:38:23 - error TS2339: Property 'map' does not exist on type 'Observable<Object>'.

38    let opens = quotes.map(theOpen => open);
                         ~~~
quote.service.ts:43:4 - error TS2322: Type 'Observable<Object>' is not assignable to type 'Observable<Quote[]>'.
  The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
    Type 'Object' is missing the following properties from type 'Quote[]': length, pop, push, concat, and 26 more.

So I changed let opens = quotes.map(theOpen => open); to let opens = quotes.pipe(map(theOpen => open));

But got the error

ERROR in quote.service.ts:39:40 - error TS2339: Property 'length' does not exist on type 'Observable<(url?: string, target?: string, features?: string, replace?: boolean) => Window>'.

39    console.log("opens.length=" + opens.length);
                                          ~~~~~~
quote.service.ts:40:18 - error TS2345: Argument of type '(item: any, index: any, array: any) => void' is not assignable to parameter of type '(value: (url?: string, target?: string, features?: string, replace?: boolean) => Window) => void'.

40    opens.forEach(function(item,index,array) {

Then I tried:

getQuotesList() {
  let quotes = this.http.get<Quote[]>(`${this.baseUrl}`);
  let opens = quotes.pipe(map(theOpen => open));
  alert(opens[0]);
  return quotes;
}

But the output was "undefined"

Then I tried

private quoteObserver = {
  next(quote) {
    console.log("quote.open=" +quote.open);
  }
}

getQuotesList() {
  let quotes = this.http.get<Quote[]>(`${this.baseUrl}`);
  of(quotes).subscribe(this.quoteObserver);
  return quotes;
}

but the output was quote.open=undefined

Then I tried

  getQuotesList(): Observable<any> {
    let quotes = this.http.get(`${this.baseUrl}`);
    quotes.subscribe(arr => {
      Object.values(arr[0].forEach(el => {
        let col = arr.map(ele => ele[el]);
        console.log(el,':', col);
      }
    )}
    return quotes;
  }

But the error was

ERROR in quote.service.ts:67:6 - error TS1005: ',' expected.

67     )}
        ~
quote.service.ts:68:5 - error TS1005: ',' expected.

68     return quotes;
       ~~~~~~


    ERROR in quote.service.ts:64:23 - error TS2339: Property 'map' does not exist on type 'Object'.

    64         let col = arr.map(ele => ele[el]);

Do you think I've made enough attempts yet? :-( I'm new to Angular/Typescript so hoping someone can guide me.

EDIT: I managed to figure how to port the code over to a linux server. Now you can access the back end to see the actual data coming in by entering this in the browser: 167.172.141.34:8080/springboot-crud-rest/api/v1/quotes

like image 847
user3217883 Avatar asked Nov 23 '25 20:11

user3217883


1 Answers

There are two pieces to this question. One is how to convert the JSON data to the array format that you want, and the other issue is how to work with Observables which wrap the actual data you're trying to access.

For the first piece, here is sample code which should convert the data format:

const quotes = [
  {"id":1,"symbol":"SP-500","date":"1927-12-30T07:00:00.000+00:00","open":17.66,"high":17.66,"low":17.66,"close":17.66,"volume":0},
  {"id":2,"symbol":"SP-500","date":"1928-01-03T07:00:00.000+00:00","open":17.76,"high":17.76,"low":17.76,"close":17.76,"volume":0}
] 

const chartData = Object.assign({}, 
  ...Object.keys(quotes[0]).map(key => ({
    [key]: quotes.map(quote => quote[key])
  })))

console.log(chartData)

And to get the data out of the observable you just subscribe to it. I've included the conversion code from above as a separate function but you could inline it as well:

getQuotesList() {
  const quotes = this.http.get(`${this.baseUrl}`)
  quotes.subscribe(quotes => this.toChart(quotes))
  return quotes
}

toChart (quotes) {
  const chartData = Object.assign({}, 
      ...Object.keys(quotes[0]).map(key => ({
          [key]: quotes.map(quote => quote[key])
      })))
  console.log(chartData)
}
like image 133
ccarton Avatar answered Nov 25 '25 09:11

ccarton