0

I try to map a Json http request answer to an object array (User) using RxJs :

My Json data looks like :

{"@context":"\/cotabe\/api\/contexts\/User","@id":"\/cotabe\/api\/users","@type":"hydra:Collection","hydra:member":[{"@id":"\/cotabe\/api\/users\/1","@type":"User","id":1,"email":"[email protected]","firstname":"Aaa","lastname":"Ggg","phone":"0606060606","mobile":"0606060607","fullName":"Aaa Ggg","username":"[email protected]","roles":["ROLE_DEVROOT","ROLE_USER"],"password":"$argon2i","createdAt":"-0001-11-30T00:00:00+01:00","updatedAt":"-0001-11-30T00:00:00+01:00","deleted":false}],"hydra:totalItems":1}

I would like to extract from that a User[], with user model :

export class User {
  constructor(
    public id: number,
    public email: string,
    public firstname: string,
    public lastname: string,
    public phone: string,
    public mobile: string,
    public roles: string[],
  ) {}
}

In my user service I have :

export class UserService {

  private users: User[] = [];
  userSubject = new Subject<User[]>();

  constructor(private apiService: ApiService) { }

  emitUsers() {
    this.userSubject.next(this.users.slice());
  }

  getUsersFromRest() {
    this.apiService.getEntriesFromRest('users').subscribe(
    (data: User[])=>{
      this.users = data['hydra:member'];
    });
    this.emitUsers();
  }
}

with in an api service

  public getEntriesFromRest (option: string): any {
    return this.httpClient.get<any[]>(this.baseEndpoint + option);
  }

I know it is an rXjs operator stuff, but I did not manage to find the solution.

3
  • The wording of the question is a little confusing - are you trying to go from an Object to JSON, or from JSON to an Object? Commented Apr 20, 2020 at 8:06
  • json to Object : I make a httpRequest, and ghet the upper Json as an answer. In this Json, I have a User list and want to populate my User[] Object with this user list, but the problem is that the User list is contained under a hydra:member key Commented Apr 20, 2020 at 8:08
  • Your api returns an object not an array this.httpClient.get<any[]> -> this.httpClient.get<any>. Use the rxjs operator map to map the returned object to your required type. This question then becomes a pure typescript/javascript question not related to Angular or RxJS in any way. See e.g. How to use TypeScript to map a large object to a smaller interface? Commented Apr 21, 2020 at 11:02

3 Answers 3

2
export class UserService {
  userSubject = new Subject<User[]>();
  userSubject$ = this.userSubject.asObservable();
  constructor(private apiService: ApiService) {}

  getUsersFromRest() {
    this.apiService
      .getEntriesFromRest("users")
      .pipe(
        map(x => JSON.stringify(x)),
        map(x => JSON.parse(x)),
        pluck("hydra:member")
      )
      .subscribe((data: User[]) => {
        this.usersSubject.next(data);
      });
  }
}

Can you try the above code

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

Comments

0
export class UserService {

  private userSubject = new Subject<User[]>();
  userSubject$ = this.userSubject.asObservable(); // If you add a public observable of your subject, you can have other components subscribe to this, and not be able to alter the subject, but still get the data.

  constructor(private apiService: ApiService) { }

  getUsersFromRest() {
    this.apiService.getEntriesFromRest('users')
      .pipe(
        map((x: any) => JSON.parse(x)) // Convert your response from JSON to an Object
      .subscribe(
        (data: User[]) => {
          this.usersSubject.next(data.hydra.member);
        });
      }
  }

There is no need to have a separate emit users method.

3 Comments

Thank you for your answer. I made the userSubject for a component (Userlist) to subscribe to it... This SuerList component may also add users... I tried implementing your method, but get errors on JSON.parse(x) : Argument of type unknow is not assignable of type string
Your other component should not alter the subject directly, it should call methods on your service to alter the userSubject. I've also edited my answer to fix your error.
SyntaxError: "JSON.parse: unexpected character at line 1 column 2 of the JSON data"
0

I am Using Angular Cli 16 It sould better if you cast the objects from Service. After that you can manage items as you like without many poblems.

import { HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs';
import { MyObject } from './myobject';

export class MyObjectService {

  constructor(private _http : HttpClient){ }
  
  readMyObjects(): Observable<MyObjects[]>{
    return this._http.get<MyObjects[]>("http://url/to/api/");          
  }
}
...

Here I found a simple tutorial that explain how interact usig HttpClient. Also on StackOverflow thera are few examples.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.