5

Сommon approach to process http response is like that:

return this._http.get(url)
           .map((res: Response) => res.json());

which provides you with an Observable<Object[]> where Object is dynamically created type from json de-serialization. Then you can use this result in *ngFor="let item of result | async" etc...

I'd like to get a specific type instance (meaning using new operator to call the type's constructor). Tried different ways to achieve something like that:

.map((res: Response) => { let obj = res.json(); return new MyObject(obj.id, obj.name);})

but getting this error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

This way seems to work but it's way too complicated and probably not effective:

.map((res: Response) => {
    let results = <MyObject[]>[];
    let obj = res.json();
    obj.forEach(
        function (o: any) {
            results.push(new MyObject(o.id, o.name));
        }
    );
    return results;
}

Thanks!

5
  • Can you try Observable<Array<Object>>? Commented Sep 10, 2016 at 21:05
  • stackoverflow.com/questions/22885995/… Commented Sep 10, 2016 at 21:41
  • 1
    *ngFor only supports arrays, not objects Commented Sep 10, 2016 at 21:41
  • See also stackoverflow.com/questions/35534959/… Commented Sep 10, 2016 at 21:45
  • @GünterZöchbauer I need to find a time to go through these posts. I hoped there's something built into Observable too achieve that. I updated my question with the the way which seems to work but I don't like it. Commented Sep 10, 2016 at 21:58

3 Answers 3

2

If you know what type of objects you want to deconstruct from the JSON (which you probably do) you can create a static method that returns an instance from Object.

class MyClass {

  prop: number;

  static fromObject(src: Object) {
    var obj = new MyClass();
    obj.prop = src.prop;
    return obj;
  }
}

Then convert the JSON response to instances of MyClass:

Rx.Observable.of('[{"prop":1},{"prop":2},{"prop":3}]')
  .map(val => JSON.parse(val))
  .exhaustMap(val => new Rx.Observable.from(val))
  .map(val => MyClass.fromObject(val))
  .subscribe(
    item => console.log('Next: ', item),
    error => console.log('Error:', error),
    _ => console.log('Completed')
  );

How this works:

  1. .map(val => JSON.parse(val)) Just converts the response to JSON which is an array of objects.

  2. .exhaustMap(val => new Rx.Observable.from(val)) Converts each value to an Observable and exhaustMap flattens them so each object from the JSON will be emitted separately.

  3. .map(val => MyClass.fromObject(val)) Use map again to convert each Object to an instance of MyClass.

See live demo: http://jsfiddle.net/f5k9zdh1/1/

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

1 Comment

Interesting. Still too much code to my taste ;) but I'll take a deeper look. Thanks.
2
.map((res: Response) => res.json().map(obj => new MyObject(obj.id, obj.name)))

1 Comment

Code-only answer are not helpful. Please attempt to explain how your code solves OP's problem. Others who find this question through search may not be as experienced as you; help them understand your answer.
0

Try this syntax, you cast it to your object:

 this.http.post(this.constants.taskUrl + parm, { headers: headers })
            .map((response: Response) => {
                var res = response.json();
                var result = <DataResponseObject>response.json();
                return result;
            })

1 Comment

The deal here is that response.json() gives you an array of objects. I updated my question with the way that seems to work but I don't like that way.

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.