martedì 1 luglio 2014

TDataSetRESTRequestAdapter: serializzare un dataset in JSON per eseguire una TRESTRequest (PUT/POST)

Introduzione

La REST Client Library è una libreria introdotta con la versione XE5 e che permette di interagire facilmente con un qualunque server REST HTTP (JSON).

Una delle funzionalità più potenti (soprattuto per un approccio RAD) di questa libreria è implementata dal componente TRESTResponseDataSetAdapter, che permette di prendere il contenuto JSON ottenuto con una chiamata REST ad un server e presentarlo in forma di TDataSet (ad esempio in una TFDMemTable). Una volta ottenuto un TDataSet, possiamo per esempio mostrare i dati ottenuti da una richiesta REST come se fossero risultati di una query database.

Trovate online diverse demo (ad esempio questo video YouTube di David Iquesto blog post di Marco Cantù e questo articolo di Sarina DuPont) di come usare il TRESTResponseDataSetAdapter.


TRESTResponseDataSetAdapter all'opera

Dal server al client, ma poi?

Grazie alla REST Client Library e al TRESTResponseDataSetAdapter, è facile interrogare un qualunque server REST HTTP JSON e portare i dati sul nostro applicativo client (mobile o desktop che sia) sotto la familiare forma di un TDataset... ma poi?

Se dobbiamo fare qualche modifica sui dati (magari attraverso una GUI e al meccanismo dei Live Bindings) e rispedirli al server, sarebbe carino avere un qualche supporto per effettuare l'operazione inversa di quella implementata da TRESTResponseDataSetAdapter.

TDataSetRESTRequestAdapter: esecuzione di UpdateRequest (a design-time)

TDataSetRESTRequestAdapter

Sostanzialmente si tratta di un componente che prende un TDataSet (con una struttura compatibile a quella generata da TRESTResponseDataSetAdapter), ne produce una serializzazione JSON e imposta di conseguenza il valore di un parametro di una TRESTRequest che può rispedire al server i dati modificati (usando una PUT o una POST, per esempio).

TDataSetRESTRequestAdapter e "Update Request" disponibile a design-time

Considerato che questo genere di necessità mi sembra abbastanza diffusa (soprattutto fra chi sta sviluppando applicazioni in cui il backend è di terze parti o sviluppato in altre tecnologie), ho pensato di mettere il codice su un mio repository GitHub.

Trovate il codice del package, del componente e di un semplice progetto di esempio al seguente indirizzo (se non avete confidenza con Git, potete scaricare uno zip direttamente dalla seguente pagina):


Alcune feature implementate:
  1. RecordsMode: possibilità di decidere se rispedire tutto il dataset, solo il record corrente o applicare un filtro custom per decidere quali record includere nella serializzazione;
  2. TargetParamName: possibilità di indicare il nome del parametro della TRESTRequest da valorizzare (chiamando il metodo UpdateRequest);
  3. supporto design-time: potete fare click-destro sul componente direttamente dall'IDE ed eseguire la serializzazione direttamente a design-time (così da poter poi eseguire anche la richiesta REST sempre a design-time, molto utile per i test e il debug);
  4. SingleObjectAsArray: se impostate RecordsMode = CurrentRecord, potete decidere se il risultato della serializzazione deve essere un TJSONObject o un TJSONArray contentente un singolo TJSONObject.

Alcune implementazioni future che mi piacerebbe realizzare:
  1. maggiore integrazione con la TRESTRequest da eseguire a valle (sto pensando di aggiungere un metodo TDataSetRESTRequestAdapter.UpdateRequestAndExecute);
  2. gestire i tipi di campi del dataset in fase di serializzazione (attualmente sono tutte stringhe, anche perchè mi risulta che il TRESTResponseDataSetAdapter non permetta di personalizzare il tipo di campi generati [forse ci stanno lavorando, in teoria dalla documentazione dovrebbe essere possibile definire le proprie FieldDefs e stabilire così i tipi dei campi da generare]);
  3. investigare se e come potrebbe essere utile sfruttare il delta dei dataset (FDMemTable o ClientDataSet) per rispedire al server solo i record modificati o qualcosa del genere (solo i campi modificati?);
  4. supporto per array innestati (non appena disponibile nella REST Client Library)

Conclusioni

TDataSetRESTRequestAdapter è un tentativo di implementare quanto indicato anche nella wiki di Delphi per permettere l'invio al server di dati modificati sul client a seguito di una richiesta REST gestita attraverso l'uso di un TRESTResponseDatasetAdapter.

Il progetto è disponibile su GitHub, spero possa esservi utile! Ogni commento/suggerimento è ben accetto!

Ciao,
Andrea