Jump to content
coenenp

TstringList properties and JSON.parse

Recommended Posts

Hello,

 

I'm using TW3HttpRequest to get a Json data string from a delphi indy http server. The request works and I'm receiving serialized data. I'm using SvSerializer in my Delphi Application. This seems to work for integer and boolean published properties. I'm having a problem

with TStringList properties.

 

This is my test class:

  TMyClass = Class
  Private
    FPublished: Boolean;
    FObjId: Integer;
    FRuleList: TStringList;
    procedure SetRuleList(const Value: TStringList);
  Public
    aPublic: Boolean;
    Constructor Create; Virtual;
    Destructor Destroy; Override;
  Published
    Property ObjId: Integer Read FObjId;
    Property aPublished: Boolean Read FPublished Write FPublished;
    Property RuleList: TStringList read FRuleList write SetRuleList;
  End;

Constructor TMyClass.Create;
Begin
  Inherited Create;
  // Default Var
  FObjId := 1000;
  FPublished := true;
  FRuleList := TStringList.Create;
End;

Destructor TMyClass.Destroy;
Begin
  // Free Var
  FRuleList.Free;
  Inherited Destroy;
End;

The ResponseText of the TW3HttpRequest in SMS:

{"ObjId":1000,"aPublished":true,"RuleList":["WIN - WIN","FTP - WIN","SFTP - WIN","WIN - SMTP","POP3 - WIN","Michel mxf & xml","PGP Encrypt","PGP Decrypt","WIN - ZIP","John","WIN - WIN","FTP - WIN","IMAP - WIN","HTTP - WIN","WIN - WIN MARY","WIN - UNZIP","Oldest","Keith","SFTP Check","Luis","Wayne","Justin","Noti Error","Concat","Speed Test","TV - Tolly","Split Output","Copy Emty Dir","WIN - WIN 2","Jason","Don H.","Michael","Empty Win Dir","Subdir Filter","labs","AUTO - WIN"]}

So in SMS I have the same test Class:

  TMyClass = class
  private
  public
  constructor create; virtual;
  published
    ObjId: Integer;
    aPublished: Boolean;
    RuleList: TstringList;
  End;

implementation

constructor TMyClass.Create;
begin
  inherited create;
  RuleList := TStringList.Create;
end;

Then the parse on http data ready:

procedure TfrmMain.HandleHttpDataReady(Sender:TW3HttpRequest);
Var
  tmpStr: String;
  tmpClass: TMyClass;
begin
  (* Document is downloaded, now display the text in our memo *)
  tmpStr := FHttp.ResponseText;
  tmpClass := TMyClass.Create;
  try
    asm
      @tmpClass = JSON.parse(@tmpStr);
    end;
    try
      mmJsonData.Text := tmpClass.ObjId.tostring;
      mmJsonData.Text := mmJsonData.Text + #13#10 + tmpClass.aPublished.ToString;
      mmJsonData.Text := mmJsonData.Text + #13#10 + tmpClass.RuleList.text;
    except
      mmJsonData.Text := mmJsonData.Text + #13#10 + 'not good';
    end;

finally tmpClass.Free; End; //mmJsonData.Text := FHttp.ResponseText; end;

The result is:

1000
True
not good

It seems that the JSON.parse doesn't work for TStringList properties. Am I doing something wrong here?

 

Advice much appreciated,

Pascal

 

Share this post


Link to post
Share on other sites

Use an "array of string" on the SmartMobileStudio side.

 

But your code won't work directly.

There is no built-in JSON serialization of published properties of a class within Smart yet.

And AFAIR there is not enough information in the RTTI to process the JSON content into properties. It will work for simple types (string/numbers), but not for classes or records.

 

The main problem is that JSON.Parse() will return a variant, not a TMyClass instance.

Also, due to variable name obfuscation, the TMyClass properties and the variant created by JSON.Parse() would probably just not match (at all!).

 

You need etheir:

- Forget about TMyClass, and use the variant directly, and its properties directly (e.g. aVariant.ObjId) - but names are case sensitive here!

- Use a function which use the JSON, convert it to a variant via JSON.Parse(), then fill the TMyClass published properties.

 

We use something like the 2nd for marshaling JSON data into SMS records or classes with out client unit wrappers for SMS.

See http://blog.synopse.info/post/2014/08/11/CrossPlatform-Clients/SmartMobileStudio

You can see at https://github.com/synopse/mORMot/blob/master/SQLite3/Samples/29%20-%20SmartMobileStudio%20Client/mORMotClient.pasan unit generated by a mORMot server (from SMS-dedicated templates), which will do all the JSON marshaling I wrote above. See for instance  TSQLRecordPeople.SetProperty() and TSQLRecordPeople.GetProperty() or Variant2TTestCustomJSONArraySimpleArray().

 

BTW our interface-based services are a very simple way of consuming server process written in Delphi from a Smart client: all marshaling is done by the framework.

You would benefit of not writing everything on your own, and get a lot of other features (like an additional remote ORM layer, security, and very good performance).

Share this post


Link to post
Share on other sites

Hello Arnaud,

 

I had to read your reply a couple of times (out of my league). 

 

Use an "array of string" on the SmartMobileStudio side.

 

 

Correct I did and it works.

 

 

There is no built-in JSON serialization of published properties of a class within Smart yet.

And AFAIR there is not enough information in the RTTI to process the JSON content into properties. It will work for simple types (string/numbers), but not for classes or records.

 

Ok .. not yet, I assumed it was available. Not so good news.

 

 

You need etheir:

- Forget about TMyClass, and use the variant directly, and its properties directly (e.g. aVariant.ObjId) - but names are case sensitive here!

- Use a function which use the JSON, convert it to a variant via JSON.Parse(), then fill the TMyClass published properties.

 

I'll try the second. I'have your unit as an example.

 

Thank You for your reply. Now I know at least why it didn't work.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×