Estava trabalhando para simplificar o TRESTClient do DataSnap e implementar alguns recursos que gostaria de ter e não encontrei no componente distribuido com o delphi ( Package para TRESTSocialClient ). Mapear as respostas Array para um TFDDataset primordial para facilitar o desenvolvimento (ex: TRESTSocialClientDataset). E quando não é possível mapear para um Dataset… código+código+bug+complexo…
Quando trabalho com um Servidor REST Datasnap escrito para delphi – a integração é simples utilizando o “Wizard” para criar um projeto REST Client disponível. Quando o servidor REST responde para múltiplas plataformas é imperativo que o servidor envie respostas “padronizadas” que sejam compatíveis com a plataforma que o cliente utiliza. O caminho mais rápido é responder JSON padrão evitando respostas específicas de uma plataforma ou outra.
Exemplo: um método não pode responder com um TDataset.Data como é o indicado pelo Delphi… isto obrigaria que o cliente seja igualmente um Delphi.. Então para manter padrão o método deve responder com um TJSONValue ou TJSONObject.
Tomando por base o Servidor Datasnap do post “FireDAC – Datasnap” onde publica o método GetCliente/{cnpj} (http://localhost:8080/datasnap/rest/TServerMethods1/GetCliente/123456) que retorna:
[code lang=”JSON”]
{"result":[{"cliente":[{"RowId":1,"codigo":1,"nome":"Embarcadero SA","cidade":"Sao Paulo","estado":"SP","endereco":"Rua…xxxx…,10","debitos":100000.12},{"RowId":2,"codigo":2,"nome":"Embarcadero SA2","cidade":"Sao Paulo","estado":"SP","endereco":"Rua…xxxx…,10","debitos":100000.12}],"adicional":[{"codigo":1,"nome":"Exemplo 2"}]}]}
[/code]
Nas andanças pelos BLOGs de MVPs encontrei um projeto “Introducing JsonToDelphiClass” que aponta para o repositório com o código do projeto.
O projeto JsonToDelphiClass permite que a representação JSON de retorno do servidor DataSnap seja colado no espaço para texto indicada e usar o botão de geração da Unit contendo a classe Delphi para a representação JSON.
As classes geradas pelo projeto possuem um método que fornecendo o código de retorno do servidor – popula o objeto delphi – facilitando a conversão da estrutura JSON para Classe.
class function FromJsonString(AJsonString: string): T... (criar a classe e popula)
.
Passando aquele retorno do Servidor, veja como ele construiu as classes para a representação JSON:
[code lang=”pascal”]
unit JsonRestServer;
// *************************************************
// Generated By: JsonToDelphiClass – 0.65
// Project link: https://github.com/PKGeorgiev/Delphi-JsonToDelphiClass
// Generated On: 2016-04-10 15:41:06
// *************************************************
// Created By : Petar Georgiev – 2014
// WebSite : http://pgeorgiev.com
// *************************************************
interface
uses Generics.Collections, Rest.Json;
type
TAdicionalClass = class
private
FCodigo: Extended;
FNome: String;
public
property codigo: Extended read FCodigo write FCodigo;
property nome: String read FNome write FNome;
function ToJsonString: string;
class function FromJsonString(AJsonString: string): TAdicionalClass;
end;
TClienteClass = class
private
FRowId: Extended;
FCidade: String;
FCodigo: Extended;
FDebitos: Extended;
FEndereco: String;
FEstado: String;
FNome: String;
public
property RowId: Extended read FRowId write FRowId;
property cidade: String read FCidade write FCidade;
property codigo: Extended read FCodigo write FCodigo;
property debitos: Extended read FDebitos write FDebitos;
property endereco: String read FEndereco write FEndereco;
property estado: String read FEstado write FEstado;
property nome: String read FNome write FNome;
function ToJsonString: string;
class function FromJsonString(AJsonString: string): TClienteClass;
end;
TResultClass = class
private
FAdicional: TArray<TAdicionalClass>;
FCliente: TArray<TClienteClass>;
public
property adicional: TArray<TAdicionalClass> read FAdicional write FAdicional;
property cliente: TArray<TClienteClass> read FCliente write FCliente;
destructor Destroy; override;
function ToJsonString: string;
class function FromJsonString(AJsonString: string): TResultClass;
end;
TRootClass = class
private
FResult: TArray<TResultClass>;
public
property result: TArray<TResultClass> read FResult write FResult;
destructor Destroy; override;
function ToJsonString: string;
class function FromJsonString(AJsonString: string): TRootClass;
end;
implementation
{TAdicionalClass}
function TAdicionalClass.ToJsonString: string;
begin
result := TJson.ObjectToJsonString(self);
end;
class function TAdicionalClass.FromJsonString(AJsonString: string): TAdicionalClass;
begin
result := TJson.JsonToObject<TAdicionalClass>(AJsonString)
end;
{TClienteClass}
function TClienteClass.ToJsonString: string;
begin
result := TJson.ObjectToJsonString(self);
end;
class function TClienteClass.FromJsonString(AJsonString: string): TClienteClass;
begin
result := TJson.JsonToObject<TClienteClass>(AJsonString)
end;
{TResultClass}
destructor TResultClass.Destroy;
var
LclienteItem: TClienteClass;
LadicionalItem: TAdicionalClass;
begin
for LclienteItem in FCliente do
LclienteItem.free;
for LadicionalItem in FAdicional do
LadicionalItem.free;
inherited;
end;
function TResultClass.ToJsonString: string;
begin
result := TJson.ObjectToJsonString(self);
end;
class function TResultClass.FromJsonString(AJsonString: string): TResultClass;
begin
result := TJson.JsonToObject<TResultClass>(AJsonString)
end;
{TRootClass}
destructor TRootClass.Destroy;
var
LresultItem: TResultClass;
begin
for LresultItem in FResult do
LresultItem.free;
inherited;
end;
function TRootClass.ToJsonString: string;
begin
result := TJson.ObjectToJsonString(self);
end;
class function TRootClass.FromJsonString(AJsonString: string): TRootClass;
begin
result := TJson.JsonToObject<TRootClass>(AJsonString)
end;
end.
[/code]