JSON – Andreano Lanusse | Tecnologia e Desenvolvimento de Software http://www.andreanolanusse.com/pt Andreano Lanusse blog - artigos, tutoriais e vídeos sobre tecnologia, desenvolvimento de software (Delphi XE4, C#, PHP, .NET) e técnicas de programação Sun, 05 May 2013 06:56:54 +0000 pt-BR hourly 1 https://wordpress.org/?v=6.5.8 TDBXJsonTools copiar/converter dados entre TDataSet – TJSONObject – DBXReader http://www.andreanolanusse.com/pt/tdbxjsontools-copiarconverter-dados-entre-tdataset-tjsonobject-dbxreader/ http://www.andreanolanusse.com/pt/tdbxjsontools-copiarconverter-dados-entre-tdataset-tjsonobject-dbxreader/#comments Mon, 19 Mar 2012 09:35:10 +0000 http://www.andreanolanusse.com/pt/?p=1478 Você pode copiar os dados de um DBXReader para um ClientDataSet e vice-versa utilizando o dbxExpress framework, provavelmente você já leu alguns dos meus  artigos aqui no blog onde explico como isso funciona em aplicações desktop, entretanto em plataformas móveis não temos o ClientDataSet e quando buscamos algo similar vem a pergunta, o que fazer? DataSnap […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
Você pode copiar os dados de um DBXReader para um ClientDataSet e vice-versa utilizando o dbxExpress framework, provavelmente você já leu alguns dos meus  artigos aqui no blog onde explico como isso funciona em aplicações desktop, entretanto em plataformas móveis não temos o ClientDataSet e quando buscamos algo similar vem a pergunta, o que fazer?

DataSnap Mobile Connectors tem um classe chamada TDBXJsonTools que permite a copia e conversão de dados entre DBXReader, TJSONObject, DBXReader e outros tipos de dados, pode ser utilizada em qualquer plataforma suportada pelos conectores, como: Java/Android, Java/BlackBerry, Objective-C, C#/Windows Phone e FreePascal.

Em aplicações desktop nativa utilizamos o TDBXDataSetReader.CopyReaderToClientDataSet(Reader, ClientDataSet) para copiar os dados do DBXReader para um ClientDataSet, no caso de aplicações móveis usamos TDBXJsonTools.CreateTDataSetFromJSON(DBXReader.asJSONObject).

Entretanto não estamos limitados a copia/conversão de dados, TDBXJsonTools traz maior flexibilidade na interação e transporte dos dados usando diferentes tipos de dados, além de usar o melhor dos tipos nativos em cada plataforma. Por exemplo, quando utilizamos DataSet em aplicações FireMonkey para iOS utilizamos a classe TDataSet que é parte da RTL do Delphi e FreePascal, já no caso de aplicações Java, TDataSet será uma extensão do TDBXReader e assim por diante.

DBXReader é unidirecional e com isso a navegação fica limitada, no entanto ao desenvolver aplicações FireMonkey para iOS você poderá copiar os dados do DBXReader para um DataSet que é bidirecional, isso irá permitir a navegação no DataSet e utilizar outros métodos do DataSet.

Abaixo a interface da classe TDBXJsonTools para FreePascal.

  TDBXJsonTools = class
  public
    class procedure jsonToDBX(obj: TJSONValue; var value: TDBXValue; dbxTypeName: String);
    class procedure JSONToValueType(json: TJSONArray; var vt: TDBXValueType);
    class function DBXParametersToJSONObject(dbxParameters: TDSParams) : TJSONObject;
    class function DBXReaderToJSONObject(dbxReader: TDBXReader): TJSONObject;
    class function CreateTDataSetFromJSON(value: TJSONObject): TDataset;
    class function TDataSetToJSONObject(value: TDataset): TJSONObject;
    class function GetTFieldTypeByTDBXDataTypes(DBXDataTypes: TDBXDataTypes) : TFieldType;
    class function GetTDBXDataTypesByTFieldType(FieldType: TFieldType) : TDBXDataTypes;
    class function CreateTStreamFromJSONArray(value: TJSONArray): TStream;
    class function StreamToJSONArray(value: TStream): TJSONArray;
    class function JSONToTableType(value: TJSONValue; dbxTypeName: String): TObject;
    class function SerializeTableType(Objetc: TObject): TJSONObject;

  end;

Eu continuo recomendando o uso do DBXReader como sua fonte principal de dados e quando necessário utilize os métodos da classe TDBXJsonTools.

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/tdbxjsontools-copiarconverter-dados-entre-tdataset-tjsonobject-dbxreader/feed/ 1
Vídeo: Serialização de objetos JSON – Delphi Conference 2010 Brasil http://www.andreanolanusse.com/pt/video-serializacao-de-objetos-json-delphi-conference-2010-brasil/ http://www.andreanolanusse.com/pt/video-serializacao-de-objetos-json-delphi-conference-2010-brasil/#comments Sat, 08 Jan 2011 01:21:07 +0000 http://www.andreanolanusse.com/pt/?p=1182 Marcela Varela apresenta na prática conceitos da representação de objetos usando JSON (Javascript Object Notation) e como usar as classes do Delphi XE para tratar conversões de objetos, simples e complexos, para este padrão, simplificando a transferência e serialização de objetos. Em função do alto volume de views dos vídeos do Delphi Conference, estamos disponibilizando […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
Marcela Varela apresenta na prática conceitos da representação de objetos usando JSON (Javascript Object Notation) e como usar as classes do Delphi XE para tratar conversões de objetos, simples e complexos, para este padrão, simplificando a transferência e serialização de objetos.

Em função do alto volume de views dos vídeos do Delphi Conference, estamos disponibilizando apenas o download para que você possa assistir em sua máquina.


Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/video-serializacao-de-objetos-json-delphi-conference-2010-brasil/feed/ 1
Apresentações do Delphi Conference 2010 disponível para download http://www.andreanolanusse.com/pt/apresentacoes-do-delphi-conference-2010-disponivel-para-download/ http://www.andreanolanusse.com/pt/apresentacoes-do-delphi-conference-2010-disponivel-para-download/#comments Thu, 18 Nov 2010 23:54:24 +0000 http://www.andreanolanusse.com/pt/?p=1117 Já está disponível o material utilizado nas apresentações do Delphi Conference 2010 Brasil, os slides disponibilizados trazem informações valiosas e link para download dos exemplos utilizados. Para efetuar o download das apresentações você precisa de uma conta no EDN (Embarcadero Developer Network), que é grátis, caso você já a tenha, efetue o login e tenha […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
Já está disponível o material utilizado nas apresentações do Delphi Conference 2010 Brasil, os slides disponibilizados trazem informações valiosas e link para download dos exemplos utilizados.

Para efetuar o download das apresentações você precisa de uma conta no EDN (Embarcadero Developer Network), que é grátis, caso você já a tenha, efetue o login e tenha acesso ao melhor conteúdo já apresentado sobre Delphi.

Artigo do EDN com todas as apresentações, clique aqui.

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/apresentacoes-do-delphi-conference-2010-disponivel-para-download/feed/ 11
Utilizando generics para transformação genérica de Objetos em DataSnap 2010 http://www.andreanolanusse.com/pt/utilizando-generics-para-transformacao-generica-de-objetos-em-datasnap-2010/ http://www.andreanolanusse.com/pt/utilizando-generics-para-transformacao-generica-de-objetos-em-datasnap-2010/#comments Wed, 24 Mar 2010 01:20:16 +0000 http://www.andreanolanusse.com/pt/?p=865 No meu post anterior “DataSnap 2010 – Enviando e Recebendo objetos” mostrei como transferir objetos através de JSON objects, nos comentários relacionados a este post Rafael Soares fez uma interessante observação com relação a necessidade de se ter que escrever em toda a classes os métodos de conversão de JSON para TObject e TObject para […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
No meu post anterior “DataSnap 2010 – Enviando e Recebendo objetos” mostrei como transferir objetos através de JSON objects, nos comentários relacionados a este post Rafael Soares fez uma interessante observação com relação a necessidade de se ter que escrever em toda a classes os métodos de conversão de JSON para TObject e TObject para JSON. Na verdade isso não é necessário, você pode utilizar generics e assim ter apenas dois métodos de conversão para qualquer classe.

O exemplo utilizado no post anterior o qual os fontes foram disponibilizados para download, traz a classe TCustomer como exemplo e implementa os método JSONtoCustomer e CustomerToJSON, este fazem referência direta a classe TCustomer, assim sendo fiz algumas modificações onde nos permitirá utilizar estes dois métodos para qualquer classe, primeiro os métodos foram renomeados para JSONtoObject e ObjectToJSON e adicionados a uma nova classe chamada TBaseObject, este métodos foram definidos como class function, desta forma não precisamos instanciar o objeto. Agora TCustomer passa a herdar desta, assim sendo qualquer objeto terá este método implemetado.

Os métodos da classe TBaseObject agora definem <T> como parâmetro de entrada e retorno, ou seja, o tipo que for definido durante a utilização do método é o que será considerado pelo método, aqui estamos utilizando Generics.

unit BaseObject;

interface

uses DBXJSON, DBXJSONReflect;

type
  TBaseObject = class
  public
    { public declarations }
    class function ObjectToJSON<T : class>(myObject: T): TJSONValue;
    class function JSONToObject<T : class>(json: TJSONValue): T;
  end;

implementation

{ TBaseObject }

class function TBaseObject.JSONToObject<T>(json: TJSONValue): T;
var
  unm: TJSONUnMarshal;
begin
  if json is TJSONNull then
    exit(nil);
  unm := TJSONUnMarshal.Create;
  try
    exit(T(unm.Unmarshal(json)))
  finally
    unm.Free;
  end;

end;

class function TBaseObject.ObjectToJSON<T>(myObject: T): TJSONValue;
var
  m: TJSONMarshal;
begin

  if Assigned(myObject) then
  begin
    m := TJSONMarshal.Create(TJSONConverter.Create);
    try
      exit(m.Marshal(myObject));
    finally
      m.Free;
    end;
  end
  else
    exit(TJSONNull.Create);

end;

end.

Já a classe TCustomer herda de TBaseObject.

unit Customer;

interface

uses
   DBXJSON, DBXJSONReflect, SysUtils, BaseObject;

type
   TMaritalStatus = (msMarried, msEngaged, msEligible);

TCustomer = class(TBaseObject)
    private
       FName: string;
       FAge: integer;
       FMaritalStatus: TMaritalStatus;
    public
        property Name: string read FName write FName;
        property Age: integer read FAge write FAge;
        property MaritalStatus: TMaritalStatus read FMaritalStatus write FMaritalStatus;

        function toString : string;override;
  end;

Agora todos os Server Methods da classe TDSServerMethods passam a utilizar os métodos de conversão de objetos especificando qual o tipo que deverá ser utilizado. O exemplo abaixo retorna uma lista de TJSONArray, cada elemento adicionado ao Array usa a sintaxe TCustomer.ObjectToJSON<TCustomer>.

<TCustomer> define que o tipo do Objeto que está sendo adicionado ao Array.

function TDSServerMethods.ListofCustomer: TJSONArray;
var
  i: Integer;
  myCustomer: TCustomer;
begin
  Result := TJSONArray.Create;

  for i := 0 to 19 do
  begin
    myCustomer := GetCustomer;
    myCustomer.Name := 'Customer ' + IntToStr(i);
    myCustomer.Age := i;
    Result.AddElement(myCustomer.ObjectToJSON<TCustomer>(myCustomer));
  end;
end;

Para ler o retorno no lado Client utilizamos o mesmo princípio com Generics, onde cada item é transformado de JSON para TCustomer conforme o exemplo abaixo:

var
  proxy: TDSServerMethodsClient;
  mySingleCustomer: TCustomer;
  allCustomers: TJSONArray;
  i: Integer;
begin

  proxy := nil;
  try
    proxy := TDSServerMethodsClient.Create
      (DMClientContainer.MyDSServer.DBXConnection);
    allCustomers := proxy.ListofCustomer;

    for i := 0 to allCustomers.Size - 1 do
    begin
      mySingleCustomer := TCustomer.JSONToObject<TCustomer>(allCustomers.Get(i));
      MMLog.Lines.Add(mySingleCustomer.ToString);
      mySingleCustomer.Free;
    end;

  finally
    proxy.Free;
  end;

Vimos aqui como Generics nos auxilia na transformação de objetos em DataSnap.

O exemplo atualizado está disponível no CodeCentral – Download do código fonte

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/utilizando-generics-para-transformacao-generica-de-objetos-em-datasnap-2010/feed/ 16
DataSnap 2010 – enviando e recebendo ARRAY de strings, numbers e outros tipos http://www.andreanolanusse.com/pt/datasnap-2010-enviando-e-recebendo-array-de-strings-numbers-e-outros-tipos/ http://www.andreanolanusse.com/pt/datasnap-2010-enviando-e-recebendo-array-de-strings-numbers-e-outros-tipos/#comments Sat, 10 Oct 2009 23:37:40 +0000 http://www.andreanolanusse.com/pt/?p=388 Dando sequência ao tema transferência de objetos com DataSnap e Delphi 2010 o qual iniciei escrevendo sobre a transferência de um simples objeto, e depois sobre o envio de array objetos, agora vamos descrever como enviar array que contenha tipos distintos. Para retornar tipos String, Integer, Double, Real, Boolean e outros tipos, utilizamos a classe […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
Dando sequência ao tema transferência de objetos com DataSnap e Delphi 2010 o qual iniciei escrevendo sobre a transferência de um simples objeto, e depois sobre o envio de array objetos, agora vamos descrever como enviar array que contenha tipos distintos.

Para retornar tipos String, Integer, Double, Real, Boolean e outros tipos, utilizamos a classe TJSONValue que serve como base para as classes TJSONString, TJSONNumber, TJSONTrue, TJSONFalse, TJSONNull e TJSONObject. O retorno de uma lista destes tipos é representando pelo TJSONArray, comentando no meu post anterior.

Abaixo exemplo de um ServerMethod que retorna um TJSONArray o qual contém vários items, cada um deles de tipos diferentes.

function TDSServerMethods.ListofDifferentTypes: TJSONArray;
var
  strval: TJSONString;
  trueval : TJSONTrue;
  falseval : TJSONFalse;
  numval: TJSONNumber;
  objval : TJSONObject;
begin
  Result := TJSONArray.Create;

  strval := TJSONString.Create('Return String value from DataSnap Server');
  Result.AddElement(strval);

  numval := TJSONNumber.Create(100);
  Result.AddElement(numval);

  numval := TJSONNumber.Create(99.99);
  Result.AddElement(numval);

  trueval := TJSONTrue.Create;
  Result.AddElement(trueval);

  falseval := TJSONFalse.Create;
  Result.AddElement(falseval);

  Result.AddElement(CustomerToJSON(GetCustomer));

end;

Agora basta acessar o método através da aplicação cliente o qual será capaz de reconhecer todos os tipos de objetos aqui enviados.

var
  proxy: TDSServerMethodsClient;
  mySingleValue: TJSONValue;
  allValues: TJSONArray;
  i: Integer;
begin

  proxy := nil;
  try
    proxy := TDSServerMethodsClient.Create
      (DMClientContainer.MyDSServer.DBXConnection);
    allValues := proxy.ListofDifferentTypes;
    for i := 0 to allValues.Size - 1 do
    begin
      mySingleValue := allValues.Get(i);

      if mySingleValue is TJSONString then
        MMLog.Lines.Add('TJSONString value ' + mySingleValue.Value)
      else if mySingleValue is TJSONNumber then
        MMLog.Lines.Add('TJSONNumber value ' + mySingleValue.Value)
      else if mySingleValue is TJSONTrue then
        MMLog.Lines.Add('TJSONTrue value ' + mySingleValue.ToString)
      else if mySingleValue is TJSONFalse then
        MMLog.Lines.Add('TJSONFalse value ' + mySingleValue.ToString)
      else if mySingleValue is TJSONObject then
        MMLog.Lines.Add('TJSONObject value ' + mySingleValue.ToString);

    end;

  finally
    proxy.Free;
  end;

end;

Ao executar o retorno será:

TJSONString value Return String value from DataSnap Server
TJSONString value 100
TJSONString value 99.99
TJSONTrue value true
TJSONFalse value false
TJSONObject value {“type”:”Customer.TCustomer”,”id”:1,”fields”:{“FName”:”Andreano Lanusse”,”FAge”:32,”FMaritalStatus”:”msMarried”}}

No caso to TJSONObject foi utilizado o método ToString o qual retorna a representação do objeto em formato JSON, através da classe TJSONUnMarshal convertermos para TCustomer, esta conversão foi tratada no posto anterior.

Download do código fonte

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/datasnap-2010-enviando-e-recebendo-array-de-strings-numbers-e-outros-tipos/feed/ 2
Utilizando callback em DataSnap 2010 http://www.andreanolanusse.com/pt/utilizando-callback-em-datasnap-2010/ http://www.andreanolanusse.com/pt/utilizando-callback-em-datasnap-2010/#comments Tue, 06 Oct 2009 07:54:40 +0000 http://www.andreanolanusse.com/pt/?p=376 Solicitação número 1 dos usuários de DataSnap, suporte a callback, DataSnap 2010 permite a execução de server methods utilizando callback, em outras palavras, é esperar que o servidor envie retornos a aplicação cliente durante o processamento. Para exemplicar melhor, imagine os famosos fechamentos de final do mês, estes são disparados a partir de uma aplicação […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
Solicitação número 1 dos usuários de DataSnap, suporte a callback, DataSnap 2010 permite a execução de server methods utilizando callback, em outras palavras, é esperar que o servidor envie retornos a aplicação cliente durante o processamento. Para exemplicar melhor, imagine os famosos fechamentos de final do mês, estes são disparados a partir de uma aplicação cliente que somente recebe um retorno ao finalizar o processo do lado servidor, com callback podemos notificar a aplicação cliente como está o processamento do lado servidor.
A classe TDBXCallback é responsável pelo callback, assim você deverá criar uma classe descendente, implementar o método execute e passar como parâmetro no seu server method. O servidor irá executar o método Execute do parâmetro de callback enviado ao servidor, na verdade o servidor está notificando o cliente para executar algum código.

Para melhor exemplificar, vamos imaginar que você precisa fazer o backup da sua base de dados a partir de uma instrução enviada pela aplicação cliente para o servidor, durante o processo de backup você deseja saber como está o andamento do backup, esta é uma tarefa para o callback, o código faz exatamento isso, backup de uma base de dados InterBase e retorna o log para a aplicação cliente.

Para começar temos que implementar o server method que será responsável por executar o backup, este obrigatoriamente necessita um parâmetro do tipo TDBXCallback o qual será responsável por enviar a notificação a aplicação cliente através do método Execute.

O método Execute por sua vez recebe envia um TJSONObject o qual contém um TJSONPair com as mensagens do log de backup da base de dados, lembre-se que eu optei por enviar apenas um valor dentro do objeto e a cada linha de log recebida o cliente será notificado que há uma mensagem nova.

procedure TDSServerBatch.StartBackup(sMessage: TDBXCallback;
  sBackupFileName: String);
var
  LCallbackValue: TJSONObject;
  db: String;

begin

  db := DMServerContainer.GetEmployeeDBName;

  srvBackup.DatabaseName := Copy(db, Pos(':', db) + 1, Length(db));

  srvBackup.Attach;
  srvBackup.BackupFile.Add(sBackupFileName);

  srvBackup.ServiceStart;
  if srvBackup.Verbose then
    while not srvBackup.Eof do
    begin

      // if srvBackup.IsServiceRunning then
      begin
        LCallbackValue := TJSONObject.Create;
        LCallbackValue.AddPair(TJSONPair.Create('Server return',
            srvBackup.GetNextLine));

        sMessage.Execute(LCallbackValue);

      end;

    end;

  if srvBackup.Active then
    srvBackup.Detach();

end;

Vamos agora ao lado cliente, como temos que passar um parâmetro do tipo TDBXCallback então teremos que criar e implementar a tal classe. Vem a pergunta, para cada server method que necessita efetuar callback terei que criar uma classe de callback? A resposta é não, neste exemplo utilizaremos anonymous method para evitar isso.

Abaixo a classe de callback que estarei utilizando, veja que o método execute recebe um parâmetro do tipo TDSCallbackMethod o qual é um anonymous method, desta forma na criação da instância desta classe será passado o código a ser executando quando o servidor executar o método Execute.

type
  TDSCallbackMethod = reference to function(const Args: TJSONValue): TJSONValue;

  TMessageCallback = class(TDBXCallback)
  private
    FCallBackMethod: TDSCallbackMethod;

  public
    constructor Create(CallBackMethod: TDSCallbackMethod);
    function Execute(const Arg: TJSONValue): TJSONValue; override;
  end;

implementation

constructor TMessageCallback.Create(CallBackMethod: TDSCallbackMethod);
begin
  FCallBackMethod := CallBackMethod;
end;

function TMessageCallback.Execute(const Arg: TJSONValue): TJSONValue;
begin
  Result := FCallbackMethod(Arg);
end;

Com a classe de callback definida, temos agora que implementar o anonymous method e executar o server method conforme o exemplo a seguir.

Veja que o parâmetro Args do anonymous method é do tipo TJSONValue, extraimos os valores TJSONPair onde se encontra o log do backup.

var
  s : TDSServerBatchClient;
begin

  callback := TMessageCallback.Create( function(const Args: TJSONValue) : TJSONValue

    var
     LJSONObject: TJSONObject; I: Integer;
     LMessage: string;
    begin
      // Extract information about the transformation from Json
      LJSONObject := TJSONObject(Args);
      Result := nil;

      for I := 0 to LJSONObject.Size - 1 do begin
         with LJSONObject.Get(I) do
           LMessage := LMessage + Format('%s ==>> "%s"', [JSonString.Value, JsonValue.Value]);

      // Display information in a listbox
        MMBackupLog.Lines.Add(LMessage);
        MMBackupLog.Update;
        Result := TJSONTrue.Create;

      end;
    end);

Na sequência apenas executamos o método, passando a classe callback com parâmetro e o anonymous method será responsável por adicionar a mensagem de retorno no campo memo que está na tela, utilizado neste exemplo.

  s := TDSServerBatchClient.Create(DMClientContainer.MyDSServer.DBXConnection);
  s.StartBackup(callback, 'mybackup.ibk');

Espero que este post tenha esclarecido as dúvidas relacionadas a callback.

Download do código fonte.

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/utilizando-callback-em-datasnap-2010/feed/ 4
DataSnap 2010 – Enviando e recebendo objetos http://www.andreanolanusse.com/pt/datasnap-2010-enviando-e-recebendo-objetos/ http://www.andreanolanusse.com/pt/datasnap-2010-enviando-e-recebendo-objetos/#comments Fri, 25 Sep 2009 00:37:13 +0000 http://www.andreanolanusse.com/pt/?p=337 Uma das perguntas frequentes dos usuários de Delphi 2009 e que utilizam DataSnap para criação de objetos é sobre a transferência de objetos entre cliente e servidor. No DataSnap 2009 estavamos limitados aos data types do dbxExpress, agora com o DataSnap 2010 que acompanha o Delphi 2010, isso é totalmente possível. DataSnap 2010 traz o […]

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
Uma das perguntas frequentes dos usuários de Delphi 2009 e que utilizam DataSnap para criação de objetos é sobre a transferência de objetos entre cliente e servidor. No DataSnap 2009 estavamos limitados aos data types do dbxExpress, agora com o DataSnap 2010 que acompanha o Delphi 2010, isso é totalmente possível.

DataSnap 2010 traz o suporte a JSON (JavaScript Object Notation) que é uma formatação leve de troca de dados, totalmente independente de linguagem, futuramente vou comentar mais sobre JSON e suas vantagens, para começar este post irá mostrar como transferir objetos entre cliente e servidores DataSnap, sendo que ambos cliente e servidor são aplicações Delphi.

Para começar vamos definir uma classe chamada TCustomer.

unit Customer;

interface

uses
   DBXJSON, DBXJSONReflect, SysUtils;

type
   TMaritalStatus = (msMarried, msEngaged, msEligible);

TCustomer = class
    private
       FName: string;
       FAge: integer;
       FMaritalStatus: TMaritalStatus;
    public
        property Name: string read FName write FName;
        property Age: integer read FAge write FAge;
        property MaritalStatus: TMaritalStatus read FMaritalStatus write FMaritalStatus;

        function toString : string;override;
  end;

Para transferir objetos em DataSnap estes devem descender the TJSONObject, no caso de não ser um objeto descendente você terá que utilizar as classes TJSONMarshal e TJSONUnMarshal para efetuar a transformação dos objetos. Sendo assim os métodos abaixo irão efetuar a conversão dos mesmos.

unit Customer;

  function CustomerToJSON(customer: TCustomer): TJSONValue;
  var
    m: TJSONMarshal;
  begin
    if Assigned(customer) then
    begin
      m := TJSONMarshal.Create(TJSONConverter.Create);
      try
        exit(m.Marshal(customer))
      finally
        m.Free;
      end;
    end
    else
      exit(TJSONNull.Create);
  end;

  function JSONToCustomer(json: TJSONValue): TCustomer;
  var
     unm: TJSONUnMarshal;
  begin
    if json is TJSONNull then
      exit(nil);
    unm := TJSONUnMarshal.Create;
    try
      exit(unm.Unmarshal(json) as TCustomer)
    finally
      unm.Free;
    end;
  end;

Com isso temos classe TCustomer pronta para trafegar entre cliente e servidor, assim sendo basta implementar um Server Method que retorne um TJSONValue a partir da transformação de TCustomer, como o exemplo abaixo.

// protected
function TServerMethods.GetCustomer: TCustomer;
begin
  Result := TCustomer.Create;
  Result.Name := 'Pedro';
  Result.Age := 30;
  Result.MaritalStatus := msEligible;
end;

// public
function TServerMethods.GetJSONCustomer(): TJSONValue;
var
  myCustomer: TCustomer;
begin
  myCustomer := GetCustomer;
  Result := CustomerToJSON(myCustomer);
  myCustomer.Free;
end;

No lado cliente ao executar o método GetJSONCustomer será necessário efetuar a transformação de TJSONValue para TCustomer, utilizando o método JSONToCustomer.

var
  proxy: TServerMethodsClient;
  myJSONCustomer: TCustomer;
begin

  try
    proxy := TServerMethodsClient.Create(SQLConnection1.DBXConnection);
    myJSONCustomer := JSONToCustomer(proxy.myJSONCustomer);

    Button1.Caption := myJSONCustomer.ToString;
    myJSONCustomer.Free;
  finally
    SQLConnection1.CloneConnection;
    proxy.Free;
  end;
end;

Muito mais pode ser feito, como retornar Arrays de objetos, classes mais complexas, etc. Estarei abordando estes temas em futuros posts.

Download do código fonte

Andreano Lanusse | Tecnologia e Desenvolvimento de Software Siga-me no Twitter: @andreanolanusse

]]>
http://www.andreanolanusse.com/pt/datasnap-2010-enviando-e-recebendo-objetos/feed/ 54