'EInsufficientRTTI exception with message 'Insufficient RTTi available to support this operation'
Trying to convert an object to JSON at run time, I'm getting insufficient RTTI Error. The object is:
{$M+}
{$TYPEINFO ON}
{$METHODINFO ON}
{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}
TMyPacket = class(TObject)
Private
FID: TGUID;
FToIP: string;
FToPort: integer;
FSent: boolean;
FSentAt: TDateTime;
FAck: boolean;
FTimeOut: Cardinal;
FDataToSendSize: UINT64;
FDataToSend: AnsiString;
public
constructor create;
destructor free;
published
property ID: TGUID read FID write FID;
property ToIP: string read FToIP write FToIP;
property ToPort: integer read FToPort write FToPort;
property Sent: boolean read FSent write FSent;
property SentAt: TDateTime read FSentAt write FSentAt;
property Ack: boolean read FAck write FAck;
property TimeOut: Cardinal read FTimeOut write FTimeOut;
property DataToSend: AnsiString read FDataToSend write FDataToSend;
end;
later in the code:
var fpacket: TMYPacket;
begin
fpacket := TVWTCPPacket.create;
//assign value to class properties
memo1.Lines.Text := TJson.ObjectToJsonString(fpacket); //throws error
and getting the error on JSON conversion. Does anyone have any idea on whats going wrong with Delphi Berlin 10.1? I do remember some RTTI issues on XE2 but not sure what is happening above is related to Delphi old bug or not.
Solution 1:[1]
Go into System.Rtti
and put a breakpoint into TRttiField.GetValue
at the line if ft = nil then
and put a breakpoint condition ft = nil
(if you would put the breakpoint in the next line you would not be able to see what the Name of the field was because of optimization).
When your debugger stops there you can inspect Self.Name
(Ctrl+F7) and it will tell you D4
which is the fourth field of your TGuid. This is because JsonReflect recursively serializes records by serializing their fields. Because D4
is declared as array[0..7] of Byte
it does not contain type info (see also).
To solve this create your own type interceptor for TGUID
:
type
TGuidInterceptor = class(TJSONInterceptor)
public
function StringConverter(Data: TObject; Field: string): string; override;
procedure StringReverter(Data: TObject; Field: string; Arg: string); override;
end;
function TGuidInterceptor.StringConverter(Data: TObject;
Field: string): string;
var
ctx: TRttiContext;
begin
Result := ctx.GetType(Data.ClassInfo).GetField(Field).GetValue(Data).AsType<TGuid>.ToString;
end;
procedure TGuidInterceptor.StringReverter(Data: TObject; Field, Arg: string);
var
ctx: TRttiContext;
begin
ctx.GetType(Data.ClassInfo).GetField(Field).SetValue(Data, TValue.From(TGuid.Create(Arg)));
end;
and mark the field accordingly:
[JsonReflect(ctString, rtString, TGuidInterceptor)]
FID: TGUID;
Solution 2:[2]
There is no RTTI generated for TGUID
kind of fields.
So in order to serialize your class, you may just use getter/setter functions, which set a string property.
Something like:
TMyPacket = class(TObject)
Private
FIDValue: TGUID;
FToIP: string;
FToPort: integer;
FSent: boolean;
FSentAt: TDateTime;
FAck: boolean;
FTimeOut: Cardinal;
FDataToSendSize: UINT64;
FDataToSend: AnsiString;
procedure SetID(const value: string);
function GetID: string;
public
constructor create;
destructor free;
property IDValue: TGUID read FID write FID;
published
property ID: string read GetID write SetID;
property ToIP: string read FToIP write FToIP;
property ToPort: integer read FToPort write FToPort
...
procedure TMyPacket.SetID(const value: string);
begin
fIDValue := StringToGUID(value);
end;
function TMyPacket.GetID: string;
begin
result := GUIDToString(fIDValue);
end;
Then serialization should work, with a "ID":
string field, and you will get the TGUID
value in the IVValue
public property.
Solution 3:[3]
check if this lines exists in the dpr file, if it exists you have to delete it
{$IFOPT D-}{$WEAKLINKRTTI ON}{$ENDIF}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Community |
Solution 2 | Arnaud Bouchez |
Solution 3 | bigbear2 |