简体   繁体   中英

Mapping an observable response as an array of custom interfaces in Angular

I have an Observable keyValue(): Observable<{[id: number]: string;}>;

The Observable's argument is:

{
    [id: number]: string;
}

As you can see the second argument haven't name

Now one result of my previous Observable was:

{1: 'Bad', 2: 'Good', 3: 'Worst', 4: 'Best', 5: 'Mean'}

I need to translate as an array of:

interface NumberKeyValue {
   id: number;
   value: string;
 }

I was trying with:

.keyValue()
  .pipe(
    map((kv) => {
      console.log(kv);
      const jsonObject = JSON.parse(JSON.stringify(kv));
      console.log(jsonObject);
      const nkvArray: NumberKeyValue[] = [];
      for (const item of jsonObject) {
        console.log(item);
        const nkv: NumberKeyValue = {
          id: 8,                                        //How to catch the id number?
          value: 'empty',                               //How to catch the string?
        };
        nkvArray.push(nkv);
      }
      return nkvArray;
    })
  )
  .subscribe((response) => {
    console.log(response);
  });

After of previous code I got:

TypeError: jsonObject is not iterable
    at MapSubscriber.project (template-sms.facade.ts:295)
    at MapSubscriber._next (map.js:29)
    at MapSubscriber.next (Subscriber.js:49)
    at TapSubscriber._next (tap.js:46)
    at TapSubscriber.next (Subscriber.js:49)
    at SwitchMapSubscriber.notifyNext (switchMap.js:70)
    at InnerSubscriber._next (InnerSubscriber.js:11)
    at InnerSubscriber.next (Subscriber.js:49)
    at MapSubscriber._next (map.js:35)
    at MapSubscriber.next (Subscriber.js:49)

First and mainly Question:How I can to translate to one Array of my NumberKeyValue interface?

Secondly: Is there a name for this type representation {[id: number]: string;} ?

The object type is indeed not iterable, but you can use Object.keys to get an array of keys that you can then use to project the data in the desired form:

.keyValue()
  .pipe(
    map((kv) => {
      // use object destructuring to get a new reference instead of
      // JSON.parse(JSON.stringify(something))
      const jsonObject = { ...kv };
      return Object.keys(jsonObject).map(key => ({ id: key, value: jsonObject[key] });
    }),
  ).subscribe((response) => {
    console.log(response);
  });

According to the Octavian Answer, as you can see, a cast is needed, using +key instead of key ; and an Array of NumberKeyValue Interface.

  .keyValue()
  .pipe(
    map((kv) => {
      const jsonObject = { ...kv };

      return Object
        .keys(jsonObject)
        .map((key) => {
          const nkv: NumberKeyValue = { id: +key, value: jsonObject[+key] };

          return nkv;
        });
    }),
  )
  .subscribe((response) => {
    console.log(response);
  });
  
  

Previously, I was thinking in archaic form.

  .keyValue()
  .pipe(
    map((kv) => {
      const numberKVArray: NumberKeyValue[] = [];
      let response = JSON.stringify(kv);
      response = response.replace(/[{}]/g, '');
      const pairs = response.split('",');
      for (const pair of pairs) {
        const property = pair.split(':"');
        property[0] = property[0].replace(/(^"|"$)/g, '');
        property[1] = property[1].replace(/(^"|"$)/g, '');
        const nkv: NumberKeyValue = {
          id: +property[0],
          value: property[1],
        };
        numberKVArray.push(nkv);
      }

      return numberKVArray;
    }),
    takeUntil(this.destroy$),
  )
  .subscribe((response) => {
    console.log(response);
  });

But, The first answer is best oriented.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM