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ó:
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
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.
Opa, que bom que te ajudou! =)
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!!!
Parabéns pelo artigo e muito obrigado.
Obrigado pelo feedback, Milton!
Excelente artigo.
Muito obrigado pelo feedback!