Serialization question

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?

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;



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;

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, 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;

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;
Thank you for the code! 

Mark, can you provide an example for TBEObjectList<T> usage?

It could be even more simplified this way:




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

Wagner R. Landgraf2019-11-19 00:52:51