You are not logged in.
Pages: 1
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
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
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
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
Yes TPerson is TSynAutoCreateFields he is unable to destroy the abstraction of the docs property after I read the json.
Offline
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
Hi Ab, it's true, I didn't think this before, . 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
Pages: 1