Share Button

Depois do XML, JSON é a mais produtiva ferramenta para trocar de informações entre diferentes objetos ou diferentes plataformas.

base
JSON é uma notação para estrutura Chave/Valor criada originalmente em JavaScript. Comparativamente ao XML, JSON é mais compacto e totalmente transparente em objetos JavaScript o que o popularizou como a estrutura mais adequada de troca de informações entre servidor e cliente.

elementar meu caro
Quando um objeto possui um estrutura de dados e se deseja enviar ou converter em outra classe ou objeto, o JSON deve ser a primeira opção para facilitar a troca de dados entre os atores da operação.
Usar uma interface tem como foco delegar ao aplicativo decidir o momento adequado para retirar a instância da memória, não precisando se preocupar com o FREE do objeto implementando algo mais próximo de um coletor de lixo existente e outras linguagens.

como usar

TInterfacedJSON representa uma implementação da interface IJSONObject para um objeto TJSONObject.

  • Unit: System.JSON.Helper;

    Gerando o IJSONObject para o dado:

    uses System.JSON.Helper;
    procedure TForm84.FormCreate(Sender: TObject);
    var
      AJson, ANome: string;
      LJson: IJsonObject;
      ACliente: Integer;
    begin
    
      AJson := '{ "cliente":1,"nome":"jose de maria" }';
    
      LJson := TInterfacedJSON.new(AJson);
      with LJson.JsonObject do
      begin
        /// pegando nome do cliente
        ANome := s('nome');
        ACliente := I('cliente');
      end;
    
      // adicionando novo key/value
      LJson.addPair('fone':'9999-9999');
    
      //....
    end;
    
  • Unit: Data.DB.Helper
    Trocando informações entre um JSON e um TDataset:

    procedure TForm84.Button1Click(Sender: TObject);
    var LJson:IJSONObject;
    begin
    
        LJson := TInterfacedJSON.new;
        LJson.addPair('cliente',1);
        LJson.addPair('nome','jose de maria');
    
        FDMemTable1.open;
        FDMemTable1.edit;
    
        // carrega os fields com o valor do JSON
        // se o JSON for um ARRAY será carrega cada posição no array como uma nova linha na tabela.
        FDMemTable1.FromJsonObject(LJson.JsonObject,True);
    
        
    
        FDMemTable1.post;
    end;
    

    Para obter um JSON do TDataset:

       // gera um array para todas as linhas
       FDMemTable1.ToJson;
    
    
       // gera o JSON somente para a linha corrente
       FDMemTable1.Fields.ToJson;
    
    
  • Unit: System.Classes.Helper;
    Lidando JSON com Objetos:

       // gera um JSON de um objeto
       MeuObjeto.ToJson;
    
    
    
       // carregando o objecto com os valor de um JSON
       MeuObjeto.FromJson(  ... );
    
    

Share Button

Trocar informações entre RECORDs com estrutura diferentes pode ser um trabalho relativamente cansativa. Uma opção é converter o RECORD de origem em JSON e em seguida carregar o JSON no RECORD de destino.
Executar esta atividade é possível fazendo uso das classes RTTI do delphi. Então a idéia mais básica é criar métodos para gerar JSON e carga do JSON com o RECORD desejado.

Uma proposta utilizando generics para lidar com JSON fontes:


 TJsonRecord<T: Record > = class
  public
     /// gerar JSON
    class function ToJson(O: T; const AIgnoreEmpty: Boolean = true;
      const AProcBefore: TProc < TJsonObject >= nil): string;
     /// carregar um JSON
    class procedure FromJson(O: T; AJson: string);
  end;

Considerando uma estrutura de RECORD (origem e destino):

     TRecordOrigem = record
       nome:string;
       email:string;
     end;


     TRecordDestino = record
       nome:string;
       email:string;
       outros:integer;
     end;

A estrutura de identificação do RECORD por generics tem por finalidade aplicar RTTI para descobrir quais os FIELDS disponíveis no RECORD a ser transformado. Assim quando queremos gerar o JSON, fazemos:

   var sJson:string;
       dados : TRecordOrigem;
   ...
   dados.nome := 'xxxx';
   dados.email := 'yyyy';

   sJson := TJsonRecord<TRecordOrigem>.ToJson(dados);   // retorna o JSON

No RECORD de destino, fazendo a carga do JSON:

   var destino:TRecordDestino;
   ...

   TJsonRecord<TRecordDestino>.FromJson(destino,sJson);

Share Button

Precisa fazer persistência local de configurações ?
Então um dia você ainda vai usar um arquivo JSON ao invés de um INI.

Ver uma classe para TJsonFile     Exemplo

  • Usando RTTI para escrever no TJsonFile

Ver o exemplo com fazer persistência de objeto usando RTTI para descobrir as propriedades a guardar no TJsonFile.WriteObject(…). Do outro lado TJsonFile.ReadObject(…) lê as propriedades no JSONFile e popula o objeto.

O funcionamento do RTTI é o mesmo descrito no post anterior

 

Share Button

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:

{"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"}]}]}

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:

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.

 

 

 

Share Button

Requer: https://github.com/amarildolacerda/helpers

Uses System.uJson;
type
   TMinhaClasse = class
   public
     Valor: Double;
     Codigo: string;
   end;

procedure TForm33.FormCreate(Sender: TObject);
var
mc: TMinhaClasse;
begin
    mc := TMinhaClasse.create;
    try
      mc.Codigo := '123456';
      mc.Valor := 10;
      ShowMessage(mc.asJson);
   finally
      mc.Free;
   end;
end;

Share Button

Com a crescente número de amigos que estão navegando em serviços
cambiáveis entre aplicativos (ou linguagens), serializar um TDataset pode ser
uma solução simples e “stander” de mercado para troca de informações.
Depois de muitas idas e vindas vou deixar o resultado do trabalho que já fiz
sobre o assunto

uses System.uJson, Data.DB.Helper;
function DatasetToJson( const ADataset:TDataset ) : string;
begin
result := ADataset.ToJson;
end;

Fonte: Data.DB.Helper.pas System.uJSON.pas