Por que o Datasnap REST retorna um JSON “sujo”?

Eu sabia que tinha um motivo, mas já tinha me esquecido! E esses dias lendo a documentação mais uma vez, “lembrei” do porque que o resultado do Datasnap é sempre um array:

{result:[<seu retorno>]}

É feito assim pois “<seu retorno>” pode não ser um valor único, visto que em Delphi podemos ter parâmetros out e var, lembra?!

Desta forma, o Datasnap está sempre pronto para pegar todos os parâmetros out e var e colocar nesse array, sendo exatamente esta a ordem: outs, vars e result. Ou seja, essa “sujeira” é pra nos ajudar a ser mais produtivos. É por conta disso que conseguimos gerar as classes proxies e construir a aplicação cliente com tanta facilidade! 😉

Poxa, mas não tinha um jeito melhor de fazer, não?! Bem, como diria o sábio Chicó:

“Não sei, só sei que foi assim…”

Para contornar isso, basta usar apenas métodos que só retornem dados pelo result (sem parâmetros var e out), assim seu array terá sempre somente uma posição. Aí você implementa o evento onFormatResult do seu componente Dispatcher…

procedure TWebModule1.DSHTTPWebDispatcher1FormatResult(Sender: TObject;
  var ResultVal: TJSONValue; const Command: TDBXCommand; var Handled: Boolean);
var
  Aux: TJSONValue;
begin
  Aux := ResultVal;
  ResultVal := TJSONArray(Aux).Items[0];
  TJSONArray(Aux).Remove(0);
  Aux.Free;
end;

…e pronto! Somiu com o Array do result! 🙂

Ah, caso não queira que a palavra “result” seja enviada também, é só acrescentar “Handled := true;” na última linha do evento onFormatResult, ficando assim:

procedure TWebModule1.DSHTTPWebDispatcher1FormatResult(Sender: TObject;
  var ResultVal: TJSONValue; const Command: TDBXCommand; var Handled: Boolean);
var
  Aux: TJSONValue;
begin
  Aux := ResultVal;
  ResultVal := TJSONArray(Aux).Items[0];
  TJSONArray(Aux).Remove(0);
  Aux.Free;
  Handled := True;
end;

Agora, se você acredita que este overhead de processamento pode prejudicar seu projeto (o que é pouco provável na maioria dos casos), considere usar o RAD Server. Mas isto é assunto para outro post 😉

Um forte abraço,
KM

Comments 4

  • Parabéns pelo artigo!

    Estou estudando servidores de aplicação DataSnap REST/JSON e é horrível esse retorno com result e um JSONArray adicional.

    Não tinha nem ideia de como tirar isso, me ajudou bastante.

  • Kelver, primeiramente parabéns pelo artigo, eu havia contornado isso de uma outra maneira, porém a sua é mais elegante!

    Um segundo problema que enfrento com o DataSnap é que o result de uma função “updateContato” (apenas exemplo) é um TJsonArray, e percebi que ele fica com vazamento de memória nesses objetos que criei para dar o result.

    function TDadosExemplo.updateContato: string;
    var
    oJsonObject:TJsonObject;
    begin
    result:=TJsonArray.Create;
    oJsonObject:=TJSONObject.Create;
    oJsonObject.AddPair(‘DESCRICAO’,’TESTE 1′);
    result.AddElement(jo);
    end;

    OBS: utilizei um método post apenas como teste. .

    Tem alguma forma de destruir esses objetos?

    • Valdenir, tem algumas coisas erradas com seu exemplo. Talvez foi porque você fez de cabeça =)
      De qualquer forma, se seu result é uma string você tem que converter o JSON para string, atribuir no result e fazer o free no objeto JSON em seguida.
      Agora, se seu result for realmente TJSONArray, não precisa (alias, não deve!) fazer free nele, pois o próprio framework o fará assim que enviar a resposta à requisição http.
      É provável que tenha algum objeto que você está criando e está ficando de fora do array ou de um outro objeto JSON “pai”, e consequentemente não está sendo destruído.
      Faça mais testes aí e qualquer coisa grita!
      Valeu!!!

Deixe sua opinião

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d blogueiros gostam disto: