Seguici su:

Angular Models Parse Json e Deserialized

Angular-Json-Parse-Deserialized-Class

Angular Models Parse Json e Deserialized

Vediamo come usare i Models in Angular, ossia usare oggetti che contengono i dati. Questo può essere utile quando si ha a che fare con delle api rest o websocket che ci inviano dati nel formato JSON e vogliamo trasformarli in oggetti ( quindi classi ) Angular e di conseguenza TypeScript. Mettiamo il caso abbiamo un api rest che ci restituisce questi dati in formato JSON. Quindi abbiamo un array con due oggetti Book che al loro interno hanno a loro volta un altro oggetto Author.

[
  {
    "id": "111111",
    "title": "Anguar 5",
    "author": {
       "firstname": "John",
       "lastname": "Doe"
    }
  },
  {
    "id": "222222",
    "title": "Java 8",
    "author": {
       "firstname": "Andrew",
       "lastname": "Jackson"
  }
 }
]

Ora creiamo il nostro progetto con angular-cli e generiamo 2 classi una di nome Book e Author con i relativi metodi get e set. Per semplicità non uso HttpClient ma setto il messaggio json in una variabile stringa, l’assegno a book e stampo il risultato nella console.

ng new ex1-json-deserialized --inline-template --inline-style

ng g class book

ng g class author
import { Author } from './author';

export class Book {

  private _id: string;
  private _title: string;
  private _author: Author;

  get id(): string {
    return this._id;
  }

  set id(value: string) {
    this._id = value;
  }

  get title(): string {
    return this._title;
  }

  set title(value: string) {
    this._title = value;
  }

  get author(): Author {
    return this._author;
  }

  set author(value: Author) {
    this._author = value;
  }
}
export class Author {

  private _firstname: string;
  private _lastname: string;


  get firstname(): string {
    return this._firstname;ex1-json-deserialized
  }

  set firstname(value: string) {
    this._firstname = value;
  }

  get lastname(): string {
    return this._lastname;
  }

  set lastname(value: string) {
    this._lastname = value;
  }
}
import { Component, OnInit } from '@angular/core';
import {Book} from "./book";

@Component({
  selector: 'app-root',
  template: ``,
  styles: []
})
export class AppComponent implements OnInit {
  books: Array<Book>;

  jsonMsg = `[
    {"id": "111111", "title": "Anguar 5", "author": { "firstname": "John", "lastname": "Doe"}},
    {"id": "222222", "title": "Java 8", "author": { "firstname": "Andrew", "lastname": "Jackson"}}
    ]`;
  
  ngOnInit(){
    this.books = JSON.parse(this.jsonMsg);
    console.log(this.books);
    console.log(this.books[0]);
  }
}

Il risultato che otteniamo non è proprio quello che ci aspettavamo, infatti noi vogliamo un array con due oggetti Book e con i rispettivi oggetti Author all’interno

(2) [{…}, {…}]
0 : {id: "111111", title: "Anguar 5", author: {…}}
1 : {id: "222222", title: "Java 8", author: {…}}

Deserializzazione

Quello che vogliamo è deserializzare il nostro Json con il nostro oggetto typescript. Per fare questo creiamo un interfaccia che ci permette di deserializzare qualsiasi oggetto.

export interface Deserializable<T> {
  deserialize(input:any): T;
}

Ho usato i generics di TypeScript cosi da poterla utilizzare per qualsiasi classe. Questa interfaccia ha un solo metodo da implementare deserialize(input:any): T;che prende in input una variabile di qualsiasi tipo. Ora implementiamo l’interfaccia nelle due classi Book e Author.

import {Deserializable} from "./deserializable";

export class Author implements Deserializable<Author>{

 private _firstname: string;
 private _lastname: string;

 get firstname(): string {
   return this._firstname;
 }

 set firstname(value: string) {
   this._firstname = value;
 }

 get lastname(): string {
   return this._lastname;
 }

 set lastname(value: string) {
   this._lastname = value;
 }

 deserialize(input: any): Author {
   Object.assign(this, input);
   return this;
 }
}
import { Author } from './author';
import {Deserializable} from "./deserializable";

export class Book implements Deserializable<Book>{

 private _id: string;
 private _title: string;
 private _author: Author;

 get id(): string {
   return this._id;
 }

 set id(value: string) {
   this._id = value;
 }

 get title(): string {
   return this._title;
 }

 set title(value: string) {
   this._title = value;
 }

 get author(): Author {
   return this._author;
 }

 set author(value: Author) {
   this._author = value;
 }


 deserialize(input: any): Book {
   Object.assign(this, input);
   this._author = new Author().deserialize(input.author);
   return this;
 }
}
export interface Deserializable<T> {
  deserialize(input:any): T;
}
import { Component, OnInit } from '@angular/core';
import {Book} from "./book";

@Component({
  selector: 'app-root',
  template: ``,
  styles: []
})
export class AppComponent implements OnInit {

  books: Array<Book>;
  booksDes: Array<Book> = [];

  jsonMsg = `[
    {"id": "111111", "title": "Anguar 5", "author": { "firstname": "John", "lastname": "Doe"}},
    {"id": "222222", "title": "Java 8", "author": { "firstname": "Andrew", "lastname": "Jackson"}}
    ]`;

  ngOnInit(){

    this.books = JSON.parse(this.jsonMsg);
    console.log(this.books);
    console.log(this.books[0]);

    (JSON.parse(this.jsonMsg))
      .map(val => this.booksDes.push( new Book().deserialize(val)));

    console.log(this.booksDes);
  }
}

Quindi non facciamo nient’altro che implementare l’interfaccia scrivendo il metodo che ci consente di convertire l’oggetto Json nel nostro oggetto Author.

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

In pratica non facciamo nulla di complicato, semplicemente utilizziamo il metodo Object.assign() che copia tutte le propietà da una sorgente ( input ) ad una destinazione ( this ).  Per quanto riguarda invece la classe Book dobbiamo fare manualmente la conversione.

deserialize(input: any): Book {
    Object.assign(this, input);
    this._author = new Author().deserialize(input.author);
    return this;
  }

Nella classe component uso JSON.parse() per trasformare la stringa in un oggeto Json e poi itero con map() inserendo ogni valore dell’array nell’ array di Book, utilizzando il metodo di deserializzazione appena creato.

(JSON.parse(this.jsonMsg))
  .map(val => this.booksDes.push( new Book().deserialize(val)));

Ora se andiamo a vedere nella console troveremo il nostro oggetto correttamente deserializzato da Json ad oggetto Typescipt

(2) [Book, Book]
0:Book {_id: "111111", _title: "Anguar 5", _author: Author}
1:Book {_id: "222222", _title: "Java 8", _author: Author}
Pasquale Guarino

pasquale.guarino80@gmail.com