1

I'm banging my head with an issue I'm having with a RXJS transformation in a Ionic 2 application. I'd like to flat a json file into object, this is my semplified json file

    [{
     "lingua": "it",
     "labels": {
        "denominazione": "Hi",
     },
     "tipologie": [
      {"denominazione": "test 1"},
      {"denominazione": "test 2"}
    ]
    },...]

this is the snippet of typescript code

    export class MyRecord{
       denominazione: string;
       label_denominazione: string;

       constructor(denominazione: string, label_denominazione: string) {
          this.denominazione = denominazione;
          this.label_denominazione = label_denominazione;
       }
    }

    public getRecords() {
       var url = '../assets/records.json'; 
       let records$ = this.http
          .get(url)
          .map(mapRecords);
    return records$;

    function mapRecords(response: Response): MyRecord[] {
       return response.json().filter(x => x.lingua == "it")
        .map(({ lingua, labels, tipologie }) => tipologie.map(tipologia =>
        toMyRecord(labels, tipologia))
       );
    }

    function toMyRecord(l: any, t: any): MyRecord{
      let record= new MyRecord(
        t.denominazione,
        l.denominazione,
      );
      return record;
    }

When I call the service:

    members: MyRecord[];
    this.myService.getRecords().subscribe(res => {
        this.members = res;
        },
        err => console.log(err)
    );

What I get in this.members is an array of array of MyRecord:

    [[{ label_denominazione: "Hi", denominazione: "test 1"}, { label_denominazione: "Hi", denominazione: "test 2"} ]]

instead of an array of MyRecord:

    [{ label_denominazione: "Hi", denominazione: "test 1"}, { label_denominazione: "Hi", denominazione: "test 2"} ]

I've tried to use flatMap (mergeMap), but I've got the error 'flatMap is not a function' (btw I've imported the operator mergeMap). I'm also wondering as this.members defined as MyRecord array can accept a different type.

0

2 Answers 2

3

Here seems to be a problem:

function mapRecords(response: Response): MyRecord[] {
   return response.json().filter(x => x.lingua == "it")
    .map(({ lingua, labels, tipologie }) => tipologie.map(tipologia =>
    toMyRecord(labels, tipologia))
   );
}

instead of 1st map try reduce like this, which merges mappings:

function mapRecords(response: Response): MyRecord[] {
   return response.json().filter(x => x.lingua == "it")
      .reduce((result, current, idx) => 
          result.concat(current.topologie.map(tipologia =>
              toMyRecord(current.labels, tipologia)));
      }, []);
}

and it should do the thing.

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

4 Comments

Thanks it works like a charm, as @alebianco has pointed out I thought to still operate with an Observable.
oh I thought that you gave up on flatMap. So to stay on Observable we would have to fix your setup first. For me it works import 'rxjs/add/operator/mergeMap';. Paste in your attempts with flatMap so that we can have a look
On second thought, why do you want stick to Observable? For me it looks like one shot request. I would do sth like get().toPromise().then(/*handleResponse*/).catch(/*handleBigNoNo*/)
That's ok, your solution works fine, as I said I got error when I replaced the first map with flatMap even if I've added the operator. I don't want to stick on Observable, I just didn't know that 'response.json()' returns a plain object. Thanks again for enlightening me.
2

response.json() returns a plain object, not an observable. From that point forward you're operating on a simple Array with the standard Array methods, which do not include flatMap.

You could convert that into an observable with Observable.from but I don't see the point in doing that based on the operation you're doing in the example. Just use a different strategy to map/reduce that Array.

Comments

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.