#1 2020-09-18 12:24:51

fabiovip2019
Member
Registered: 2019-03-14
Posts: 76

Serialization of abstraction

Hi Ab,
I have a problem to serialize an object that has an abstraction, Is there any way to do it? I'll post the object below for you to understand.

 TPerson= class(TAbstractPerson)
 protected
           FDocs: TDocs;
    published
         property Docs:TDocs Read FDocs;
  end;   

TDocs= class Abstract(TSynAutoCreateFields)
  end;

TDocsPF = class(TDocs)
  private
    FCPF: TCPF;
  public
  published
    property CPF: TCPF read FCPF write FCPF;
  end;  

TDocsPJ = class(TDocs)
  private
    FCNPJF: TCNPJ;
  public
  published
    property CPNJ: TCNPJ read FCNPJFwrite FCNPJF;
  end;                                                                     

is it possible to serialize this docs property of the TPerson object?
I thought about being a variant, the problem with the variant is that I can't identify the type of the instance afterwards. I don't know if I made myself clear

Last edited by fabiovip2019 (2020-09-18 12:25:57)

Offline

#2 2020-09-18 13:31:30

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: Serialization of abstraction

Wouldn't this cause you problems later when using this class?

You will have to check the instance whenever you need to get the value.

if person.docs is TDocsPJ then..
else if person.docs is TDocsPF then...

What if you create a field to define the type of document?

TDocType = (dcCPF, dcCNPJ, dcRG, dcCNH);

 TPerson= class(TAbstractPerson)
 protected
        FDoc: RawUtf8;
        FDocType: TDocType;
    published
         property Doc:RawUtf8 Read FDoc write FDoc;
         property Doc:TDocType  Read FDocTypewrite FDocType;
  end;   

Last edited by macfly (2020-09-18 13:32:21)

Offline

#3 2020-09-18 17:36:00

fabiovip2019
Member
Registered: 2019-03-14
Posts: 76

Re: Serialization of abstraction

Hi Macfly, this field exists, I just omitted it because I don't consider this class more fields like name, email, phone and one of them is the type. The TDocs abstraction classes also have more properties. I just omitted it for the example. But really Macfly I need to be testing the type whenever I need to recover this class, but my problem is being serialization. I managed to serialize the abstraction using TJSONSerializer.RegisterCustomSerializer and it looks like this:

class function TPerson.DocsClassReader(const aValue: TObject;
  aFrom: PUTF8Char; var aValid: Boolean; aOptions: TJSONToObjectOptions
  ): PUTF8Char;
var V: TPerson absolute aValue;
    Values: array[0..4] of TValuePUTF8Char;
begin
  result := JSONDecode(aFrom,[
  'Name',
  'TypeDocs',
  'Docs'
  ],@Values);
  aValid := (result<>nil);
  if aValid then begin
    V.FName := Values[0].ToUTF8;
    v.FTypeDocs:= TTypeDocs( Values[1].ToInteger);
    case V.FTypeDocs of
     tpPF:begin
     V.FDocs:= TDocsPF.Create; //here is the problem there is a memory leak
     ObjectLoadJSON( V.FDocs,Values[2].ToUTF8);
     end;
     tpPJ:begin
     V.FDocs:= TDocsPJ.Create;
     objectLoadJSON(V.FDocs,Values[2].ToUTF8);
     end;
    end; 
   

  end;       

Offline

#4 2020-09-18 18:28:12

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: Serialization of abstraction

What is the base type of TAbstractPerson?

TSynAutoCreateFields manages the instances for you, but in this case the container object must be a TSynAutoCreateFields, that is "TPerson".

 TPerson= class(TSynAutoCreateFields)
 protected
           FDocs: TDocs;
    published
         property Docs:TDocs Read FDocs; //TSynAutoCreateFields manage this field
  end;   

If you cannot leave TPerson as TSynAutoCreateFields then I believe that you should destroy the objects explicitly in the Destructor,  Destroy method.

Offline

#5 2020-09-18 19:36:20

fabiovip2019
Member
Registered: 2019-03-14
Posts: 76

Re: Serialization of abstraction

Yes TPerson is TSynAutoCreateFields he is unable to destroy the abstraction of the docs property after I read the json.

Offline

#6 2020-09-19 06:03:29

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Serialization of abstraction

TSynAutoCreateFields means that it will auto-create fields.
So a V.FDocs is created when you create TPerson.

Therefore, when you write:

V.FDocs:= TDocsPF.Create; 

There is already a V.FDocs existing, so your code is leaking memory.
You need to free V.FDocs first if you want to replace it.

Offline

#7 2020-09-21 12:12:26

fabiovip2019
Member
Registered: 2019-03-14
Posts: 76

Re: Serialization of abstraction

Hi Ab, it's true, I didn't think this before, sad. A simple free on FDocs solved the problem. Thank you very much Ab and MacFly. a lot of it. I found it a bit complicated to keep this serialization with abstraction, is there a better way?

Offline

Board footer

Powered by FluxBB