0

I am trying to map my JSON array objects from my server to an angular model. I believe the best place to do this is as soon as I have them in the pipe at map. Not sure how I can do this with the map operator.

Later on I use a complex data source process to fill my table and paginate. I do not see how I could break up the json after this initial get from the server.

I have tried using classes and constructors. I have tried creating another class that takes the list of that particular model. And I have tried using a deserilizable method on the class. I believe there must be an angular magic way of doing this as interfaces. Any ideas?

p.s Still new to reactive programming!

     export class PlaylistService {

      constructor(private http: HttpClient) { }

      findPlaylistTracks(
           playlistId: string, filter = '', sortOrder = 'asc',
           pageNumber = 0, pageSize = 3): Observable<PlaylistItem[]> {

    return this.http.get<PlaylistItem[]>('api/spotify/playlist- item',{
            params: new HttpParams()
                .set('playlistId', playlistId.toString())
                .set('filter', filter)
                .set('sortOrder', sortOrder)
                .set('pageNumber', pageNumber.toString())
                .set('pageSize', pageSize.toString())
            })
    .pipe(
          map((res: PlaylistItem[]) => <PlaylistItem[]>res['payload']),
          tap( val => console.log('are they mapped to models ?',val)));
        }
    }
    export interface PlaylistItem {

      albumInfo: PlayListAlbum;
      artists: PlayListArtist;
      playlistName: string;
      trackNumber: number;
      trackDuration: string;
      trackUri: string;

    }

     export interface PlayListArtist{

       artistName: string;
       fullArtistInfo: string;

    }


     export interface PlayListAlbum{

       albumName: string;
       relatedAlbums: string;

     }
{playlist_name: "Dubliners", track_name: "Seven Drunken Nights - 1993 
Remaster", album_info: {…}, artists: {…}, track_duration: "3:46", …}
{playlist_name: "Dubliners", track_name: "The Black Velvet Band", 
album_info: {…}, artists: {…}, track_duration: "3:36", …}
{playlist_name: "Dubliners", track_name: "The Foggy Dew", album_info: 
{…}, artists: {…}, track_duration: "3:42", …}

No errors. The val in the tap() log still prints the json key/values.

4
  • 1
    Can you please share a portion of the response which has key/value pair? We will be able to better answer as per your current code. Commented Jul 3, 2019 at 18:57
  • Ok I did so. @user2216584 Commented Jul 3, 2019 at 19:12
  • 1
    Dont expect your json with different properties name to map itself to your PlaylistItem. You need to build the object yourself in the tap or use a class instead of an interface to be able to use new and map it in the constructor. Commented Jul 3, 2019 at 19:36
  • Ok so I created three class and implemented Deserializable on each with the required method. According to angular convention though class variables should be camel case, now I left them as snake case to not have to manually assign each json key to its corresponding camel case, because it feels long winded and loathsome to do so. Any thoughts on this @ukn Commented Jul 5, 2019 at 17:13

1 Answer 1

1

This is what I did in the end:

created this interface.

export interface Deserializable {
     deserialize(input: any): this;
  }

added it to my classes

export class PlaylistItem implements Deserializable {

  public album_info: PlayListAlbum;
  public artists: PlayListArtist;
  public playlist_name: string;
  public track_number: number;
  public track_duration: string;
  public track_uri: string;
  public track_name: string;

  deserialize(input: any) {
    Object.assign(this, input);
    this.album_info = new PlayListAlbum().deserialize(input.album_info);
    this.artists = new PlayListArtist().deserialize(input.artists);
    return this;
  }
}

export class PlayListAlbum implements Deserializable {

  public album_name: string;
  public related_albums: string;

  deserialize(input: any): this {
    return Object.assign(this, input);
  }
}

export class PlayListArtist implements Deserializable {

  public artist_name: string;
  public full_artist_info: string;

  deserialize(input: any): this {
    return Object.assign(this, input);
  }
}

Then did the conversion in Pipe() -> Map() like so:

  }).pipe(
      map(res => res['payload'].map(data => new PlaylistItem().deserialize(data)))
          );
    }

I have to use snake case like the json. But it works. Now I have angular models.

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

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.