Web forum is in read-only mode. Login as active registered customer for write access
  Forum Search   New Posts New Posts

Serialization question

 Post Reply Post Reply
Author
Alex Egorov View Drop Down
Member
Member
Avatar

Joined: 04 May 2017
Posts: 53
Post Options Post Options   Quote Alex Egorov Quote  Post ReplyReply Direct Link To This Post Topic: Serialization question
    Posted: 12 Nov 2019 at 8:44am
Hello, I'm trying to test serialization:

type
  TRecTest = class
  private
    FS1: string;
    FI1: Integer;
  public
    property  S1: string read FS1 write FS1;
    property  I1: Integer read fI1 write fI1;
    function  ToJSON: string;
  end;

function TRecTest.ToJSON: string;
var
  Serializer: TDataSnapJsonSerializer;
  jValue: TJsonValue;
begin
  Serializer := TDataSnapJsonSerializer.Create;
  try
    jValue := Serializer.ToJson(Self);
    Result := jValue.ToJSON;
  finally
    Serializer.Free;
  end;
end;

// testing
var
  R: TRecTest;
  sJSON: string;
...
  R := TRecTest.Create;
  R.S1 := 'Test Str';
  R.I1 := 123;
  sJSON := R.ToJSON;
  // here is sJSON = {"$type":"fTest.TRecTest","$id":1}

Why sJSON is not contained values ​​of fields?
Back to Top
Bracey Mark View Drop Down
New Member
New Member
Avatar

Joined: 02 Aug 2012
Posts: 17
Post Options Post Options   Quote Bracey Mark Quote  Post ReplyReply Direct Link To This Post Posted: 13 Nov 2019 at 7:00pm
Since you own Aurelius I would use the JSON serializer supplied with it.

It is located in \TMS Busines Core Library\source\core 

with units Bcl.Json.Deserializer, Bcl.Json.Serializer,  Bcl.Json.Attributes,

Your class would look like this using it.


[JsonNamingStrategy(TDefaultNamingStrategy)] 
TRecTest = class
  private
    FS1: string;
    FI1: Integer;
  public
    [JSONProperty]
    property  S1: string read FS1 write FS1;
    [JSONProperty]
    property  I1: Integer read fI1 write fI1;
    function  ToJSON: string;
  end;


function TRecTest.ToJson: String;
var JS : TJsonSerializer;
var V : TValue;
    TT :  TTypeToken;
    SS : TStringStream;
begin
 V := TValue.From(Self);
 TT := TTypeToken.Create( V.TypeInfo);
 try
  SS := TStringStream.Create;
  JS := TJsonSerializer.Create;
  JS.Write(V,TT, SS);
  Result := SS.DataString;
 finally
  JS.Free;
  SS.Free;
 end;



Back to Top
Alex Egorov View Drop Down
Member
Member
Avatar

Joined: 04 May 2017
Posts: 53
Post Options Post Options   Quote Alex Egorov Quote  Post ReplyReply Direct Link To This Post Posted: 14 Nov 2019 at 4:59pm
Thank you, your code works! And also my code works too with small additions for class:
  [Entity]
  TRecTest = class
  private
    FS1: string;
    FI1: Integer;
  public
    [Column('S1', [TColumnProp.Required])]
    property  S1: string read FS1 write FS1;
    [Column('I1', [TColumnProp.Required])]
    property  I1: Integer read fI1 write fI1;
    function  ToJSON: string; ;
  end;
Back to Top
Alex Egorov View Drop Down
Member
Member
Avatar

Joined: 04 May 2017
Posts: 53
Post Options Post Options   Quote Alex Egorov Quote  Post ReplyReply Direct Link To This Post Posted: 14 Nov 2019 at 7:20pm
Mark, your code can be shortened to:

function TRecTest.ToJSON: string;
var
  JS: TJsonSerializer;
begin
  JS := TJsonSerializer.Create;
  try
    Result := JS.WriteAs<TRecTest>(Self);
  finally
    JS.Free;
  end;
end;
Back to Top
Bracey Mark View Drop Down
New Member
New Member
Avatar

Joined: 02 Aug 2012
Posts: 17
Post Options Post Options   Quote Bracey Mark Quote  Post ReplyReply Direct Link To This Post Posted: 14 Nov 2019 at 9:41pm
It could, but I have a base class that I can derive from which has implemented in the base

LoadFrom
SaveTo

Strings, Streams, Files 

and my method allows for that.

I also use a Generic TObjectList to do the same kind of thing.

e.g.
procedure TBEObjectList<T>.LoadFromStream(const Stream: TStream; const ITS : TInstanceTypeSerialization = TInstanceTypeSerialization.IfNeeded);
var V : TValue;
    JD : TJsonDeserializer;
    TT :  TTypeToken;
begin
 Clear;
 V := TValue.From(Self);
 TT := TTypeToken.Create( V.TypeInfo);
 JD := TJsonDeserializer.Create;
 JD.Converters.ObjectConverterFactory.InstanceTypeSerialization := ITS;
 try
  Stream.Position := 0;
  JD.Read(Stream, V, TT);
 finally
  JD.Free;
 end;
end;
Back to Top
Bracey Mark View Drop Down
New Member
New Member
Avatar

Joined: 02 Aug 2012
Posts: 17
Post Options Post Options   Quote Bracey Mark Quote  Post ReplyReply Direct Link To This Post Posted: 14 Nov 2019 at 9:50pm
I have two base classes 
TBaseEntity 
and 
TBEObjectList<T: TBaseEntity> = class(TObjectList<T>)

which I use to bind to the TMSAureliusDataset and my generic serialization works well for that.

e.g. my TBaseEntity LoadFromJson method.


procedure TBaseEntity.LoadFromJson(const Json: String);
var V : TValue;
    JD : TJsonDeserializer;
    TT :  TTypeToken;
begin
 V := TValue.From(Self);
 TT := TTypeToken.Create( V.TypeInfo);
 JD := TJsonDeserializer.Create;
try
  JD.Read(Json,V, TT);
  Loaded;
 finally
  JD.Free;
 end;

end;
Back to Top
Alex Egorov View Drop Down
Member
Member
Avatar

Joined: 04 May 2017
Posts: 53
Post Options Post Options   Quote Alex Egorov Quote  Post ReplyReply Direct Link To This Post Posted: 17 Nov 2019 at 1:16pm
Thank you for the code! 

Mark, can you provide an example for TBEObjectList<T> usage?
Back to Top
Wagner R. Landgraf View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 2567
Post Options Post Options   Quote Wagner R. Landgraf Quote  Post ReplyReply Direct Link To This Post Posted: 19 Nov 2019 at 12:52am
Originally posted by Alex Egorov

Mark, your code can be shortened to:

function TRecTest.ToJSON: string;
var
  JS: TJsonSerializer;
begin
  JS := TJsonSerializer.Create;
  try
    Result := JS.WriteAs<TRecTest>(Self);
  finally
    JS.Free;
  end;
end;

It could be even more simplified this way:

function TRecTest.ToJSON: string;
begin
    Result := TJson.SerializeAs<TRecTest>(Self);
end;


Edited by Wagner R. Landgraf - 19 Nov 2019 at 12:52am
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down