Blog
All Blog Posts | Next Post | Previous PostAurelius objects everywhere - Distributed applications using JSON
Thursday, December 13, 2012
TMS Aurelius version 1.7, released a couple of weeks ago, introduced a new feature that was often requested by users: JSON support. You may ask yourself, why is that so important? Can't I "use JSON" already with Delphi itself using JSONMarshal class, or even by a 3rd party library like Super Object?Well, yes and no. Actually there are already many people using Aurelius in distributed applications, using it with DataSnap, REST servers. etc.. My previous blog post is an example of that. If you have in your application simple entity classes like this:
[Entity, Automapping] TCustomer = class private FId: Integer; FName: string; FCity: string; public property Id: Integer read FId write FId; property Name: string read FName write FName; property City: string read FCity write FCity; end;
But you might also want to benefit from many Aurelius features: nullable types, lazy-loading, blob support, associations, lists. That's when the problem arises. Most JSON libraries don't handle them correctly. Some of them allow you to add some custom converters and attributes that maybe would make it happen, but it would pollute your class (why add extra meta information when your mapping is already done) and probably will require many hours of extra effort to make it work.
So, that 's the reason for this new feature - it takes advantage of the mapping information for the serialization and deserialization. Aurelius already knows which fields/properties are important (mapped), the custom types, the lists, associations, etc.. So for example, to build a DataSnap REST server that has methods returning objects, you can simply implement your server methods like this;
function TBugTrackerMethods.LoadIssue(Id: integer): TJsonValue; begin Result := FSerializer.ToJson(FManager.Find<TIssue>(Id)); end; procedure TBugTrackerMethods.SaveIssue(Issue: TJsonValue); begin FManager.SaveOrUpdate(FDeserializer.FromJson<TIssue>(Issue)); FManager.Flush; end; function TBugTrackerMethods.ListIssuesByProject(ProjectId: integer): TJsonValue; var IssueList: TList<TIssue>; begin IssueList := FManager.Find<TIssue> .SubCriteria('Project') .Where(TLinq.IdEq(ProjectId)) .List<TIssue>; try Result := FSerializer.ToJson(IssueList); finally IssueList.Free; end; end;
var issue = null; $(document).ready(function() { $('#issuediv').hide(); $('#searchButton').click(function(event) { issue = serverMethods().LoadIssue(issueIdField.value).result; $('#issuediv').show(); $('#idField').val(issue.Id); $('#subjectField').val(issue.Subject); $('#priorityField').val(issue.Priority); $('#statusField').val(issue.Status); $('#assignedToField').val(issue.AssignedTo.Name); $('#projectField').val(issue.Project.Name); $('#descriptionField').val(issue.Description); }); $('#closeButton').click(function(event) { issue.Status = 'Closed'; serverMethods().SaveIssue(issue); $('#issuediv').hide(); }); $('#cancelButton').click(function(event) { issue.Status = 'Canceled'; serverMethods().SaveIssue(issue); $('#issuediv').hide(); }); });
Wagner Landgraf
This blog post has received 6 comments.
2. Tuesday, January 15, 2013 at 3:54:41 PM
We would like to support it, but as far as I know it doesn''t provide the same RTTI library that is available in Delphi, so it''s not compatible. If it becomes more compatible, we can consider, yes.
Wagner Landgraf
3. Wednesday, March 6, 2013 at 9:33:30 AM
Hi,
Where I can find the source code of this example?
Where I can find the source code of this example?
Rafael
4. Friday, March 8, 2013 at 7:53:05 AM
Hi,
Congratulations on the good work with Aurelius.
Is there any possibility of providing the example presented in this post to download?
Congratulations on the good work with Aurelius.
Is there any possibility of providing the example presented in this post to download?
Rafael
5. Friday, March 8, 2013 at 8:01:12 AM
Thank you! Please send an e-mail to our support e-mail so we can talk more about this demo.
Wagner Landgraf
6. Monday, January 27, 2014 at 1:49:52 PM
Boa tarde Wagner,
Estamos estudando a utilização do TMS Aurelius, e estamos com dúvida com relação a utilização dele com DataSnap REST.
Quando recebemos do servidor uma lista de objetos JSON, tal como abaixo:
{"result":[[
{"$type":"PapelModel.TPapelModel","$id":1,"FID":1,"Nome":"GERENTE","Descricao":"GEN"},
{"$type":"PapelModel.TPapelModel","$id":2,"FID":2,"Nome":"SUPERVISOR","Descricao":"SUP"},
{"$type":"PapelModel.TPapelModel","$id":3,"FID":3,"Nome":"ADMINISTRADOR","Descricao":"ADM"}
]]}
Estou usando a função abaixo para deserializar o objeto JSON de retorno
class function TJsonManager.JSONToObject<T>(AValue: TJSONValue): T;
var
Deserializer: TDataSnapJsonDeserializer;
begin
if AValue is TJSONNull then
Exit(nil);
Deserializer:= TDataSnapJsonDeserializer.Create;
try
Result:= Deserializer.FromJson<T>(AValue);
finally
Deserializer.Free;
end;
end;
Porem quando eu faço a deserialização do objeto para um TList<TPapelModel> é gerada uma exceção:
class function TPapelController.Find: TList<TPapelModel>;
var
ResponseStream: TStringStream;
begin
try
ResponseStream := TStringStream.Create;
try
Get(ResponseStream);
Result := TJsonManager.JSONToObject<TList<TPapelModel>>(TJsonManager.JSONStringStreamToJSONValue(ResponseStream));
finally
ResponseStream.Free;
end;
except
on E: Exception do
Application.MessageBox(PChar(''Ocorreu um erro durante a consulta. Informe a mensagem ao Administrador do sistema.'' + #13 + #13 + E.Message), ''Erro do sistema'', MB_OK + MB_ICONERROR);
end;
end;
EIncompatibleJsonValueType with message ‘Incompatible jsonvalue Cannot serialize to proper type.
Você poderia me orientar sobre a falha que estamos cometendo no processo?
Estamos estudando a utilização do TMS Aurelius, e estamos com dúvida com relação a utilização dele com DataSnap REST.
Quando recebemos do servidor uma lista de objetos JSON, tal como abaixo:
{"result":[[
{"$type":"PapelModel.TPapelModel","$id":1,"FID":1,"Nome":"GERENTE","Descricao":"GEN"},
{"$type":"PapelModel.TPapelModel","$id":2,"FID":2,"Nome":"SUPERVISOR","Descricao":"SUP"},
{"$type":"PapelModel.TPapelModel","$id":3,"FID":3,"Nome":"ADMINISTRADOR","Descricao":"ADM"}
]]}
Estou usando a função abaixo para deserializar o objeto JSON de retorno
class function TJsonManager.JSONToObject<T>(AValue: TJSONValue): T;
var
Deserializer: TDataSnapJsonDeserializer;
begin
if AValue is TJSONNull then
Exit(nil);
Deserializer:= TDataSnapJsonDeserializer.Create;
try
Result:= Deserializer.FromJson<T>(AValue);
finally
Deserializer.Free;
end;
end;
Porem quando eu faço a deserialização do objeto para um TList<TPapelModel> é gerada uma exceção:
class function TPapelController.Find: TList<TPapelModel>;
var
ResponseStream: TStringStream;
begin
try
ResponseStream := TStringStream.Create;
try
Get(ResponseStream);
Result := TJsonManager.JSONToObject<TList<TPapelModel>>(TJsonManager.JSONStringStreamToJSONValue(ResponseStream));
finally
ResponseStream.Free;
end;
except
on E: Exception do
Application.MessageBox(PChar(''Ocorreu um erro durante a consulta. Informe a mensagem ao Administrador do sistema.'' + #13 + #13 + E.Message), ''Erro do sistema'', MB_OK + MB_ICONERROR);
end;
end;
EIncompatibleJsonValueType with message ‘Incompatible jsonvalue Cannot serialize to proper type.
Você poderia me orientar sobre a falha que estamos cometendo no processo?
Antonio Baceiredo
All Blog Posts | Next Post | Previous Post
Regards,
Anderson Farias