Serializing JSON object for an instance instantiated through a metaclass

973 views Asked by At

The SuperObject library has a generic method for serializing objects:

type
   TSomeObject = class
   ...
   end;

var
   lJSON       : ISuperObject;
   lContext    : TSuperRttiContext;
   lSomeObject : TSomeObject;
begin
   lSomeObject := TSomeObject.Create;
   lContext := TSuperRttiContext.Create;
   lJSON := lContext.AsJson<TSomeObject>(lSomeObject);

But now I'm dealing with metaclass instances.
This is the object structure:

TJSONStructure = class(TObject);

TReqBase = class(TJSONStructure)
private
   token: Int64;
public
end;

TReqLogin = class(TReqBase)
private
   username,
   password: String;
   module  : Integer;
public
end;


type
   TWebAct = (ttlogin,
              ttsignin);

TReqClass = class of TReqBase;

const
   cWebActStructures: Array[TWebAct] of
   record
      RequestClass : TReqClass;
   end
   = (
      { ttlogin  } (RequestClass: TReqLogin;),
      { ttsignin } (RequestClass: TReqSignIn;)     // Not in definitions above
     ); 

If I now try:

var
   lContext      : TSuperRttiContext;
   lJSON         : ISuperObject;
   lRequestClass : TReqClass;
   lRequestBase  : TReqBase;
begin
   lRequestClass := cWebActStructures[ttlogin].RequestClass;
   lRequestBase := lRequestClass.Create;     // instance of type TReqLogin
   lContext := TSuperRttiContext.Create;
   lJSON := lContext.AsJson<TReqBase>(lRequestBase);

I get the TReqBase serialized: lJSON.AsString = '{"token":-12346789}'
I want to have TReqLogin serialized.
Tried:

  • lContext.AsJson< TReqLogin >(lRequestBase); won't work: incompatible types) [Besides, I would have to list/handle all possible RequestClass types in my routine]

  • lContext.AsJson< lRequestBase.ClassType >(lRequestBase) neither: E2531 Method 'AsJson' requires explicit type argument(s)

Is there any way I can have my lRequestBase serialized as a TReqLogin, TReq... without having to code for them all?

1

There are 1 answers

0
Jan Doggen On BEST ANSWER

The trick is to not create a TSuperRttiContext and call its AsJSOn method myself, but to immediately use:

lJSON := RequestBase.ToJSON;

The ToJSON method will then create a TSuperRttiContext behind the scenes and handle the necessary conversions.

With a big thank you to Marjan for her help.