Es liegt, wie jaenicke andeutet, an der Typ-Definition für D4.
Das array[0..7] of Byte bekommt die
Rtti nicht als Typ aufgedröselt.
Vielleicht ein Bug, weil anscheinend die
Rtti immer einen richtigen Alias-Namen braucht.
Beim Erstellen des notwendigen
TRttiField
für D4, wird der FFieldType nicht ordentlich aufgelöst.
Die PTypeInfo dafür müsste als TTypeKind.tkArray rauskommen.
Delphi-Quellcode:
constructor TRttiField.Create(APackage: TRttiPackage; AParent: TRttiObject;
var P: PByte);
begin
inherited Create(APackage, AParent, P);
FFieldType := GetFieldType;
// hier kommt nil zurück für statische Arrays.
FOffset := GetOffset;
end;
...
function TRttiRecordField.GetFieldType: TRttiType;
begin
Result := Pool.TypeOrNil(
Handle^.Field.TypeRef);
//TypeRef ist hier nil, daher kommt von TypeOrNil auch nichts zurück. Das passiert schon beim Erzeugen des Basis-Typs TRttiObject im constructor
end;
Darum ist in
TJsonSerializerWriter.WriteProperty
in Zeile 1361
AProperty.Contract := ResolveContract(AProperty.TypeInf);
der Wert für AProperty.TypeInf nil und es kommt kein vernünftiger Contract: TJsonContract bei raus.
Du kannst dich zumindest dahingehend behelfen, indem du dir einen Hilftyp zusammen schusterst und später dann immer zwischen deinen
GUID-Typ und den richtigen TGUID-Typ aus der
RTL castest:
Konsolenbeispiel:
Delphi-Quellcode:
program Project6;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
System.JSON,
System.JSON.Serializers;
type
// TMyGUID = TGUID;
TMyArray =
array [0 .. 7]
of Byte;
TMyGUID =
record
public
D1: Cardinal;
D2: Word;
D3: Word;
D4: TMyArray;
class function NewGuid: TMyGUID;
static;
function ToString:
string;
end;
class function TMyGUID.NewGuid: TMyGUID;
var
foo: TGUID;
begin
foo := TGuid.NewGuid;
Result.D1 := foo.D1;
Result.D2 := foo.D2;
Result.D3 := foo.D3;
Result.D4 := TMyArray(foo.D4);
end;
function TMyGUID.ToString:
string;
begin
Result := TGuid(Self).Tostring;
end;
var
lGuid, lNewGuid: TMyGUID;
lText: TStringList;
lJson:
string;
lSerializer, lDeserializer: TJsonSerializer;
begin
try
lText := TStringList.Create;
try
lGuid := TMyGUID.NewGuid;
lText.Add(lGuid.ToString);
lSerializer := TJsonSerializer.Create;
try
lJson := lSerializer.Serialize<TMyGUID>(lGuid);
finally
FreeAndNil(lSerializer);
end;
lText.Add(lJson);
lDeserializer := TJsonSerializer.Create;
try
lNewGuid := lDeserializer.Deserialize<TMyGUID>(lJson);
finally
FreeAndNil(lSerializer);
end;
lText.Add(lNewGuid.ToString);
Writeln(lText.Text);
finally
FreeAndNil(lText);
end;
except
on E:
Exception do
Writeln(E.ClassName, '
: ', E.
Message);
end;
Readln;
end.
Über den Call Stack TJsonDefaultContractResolver.ResolveContract | TJsonDefaultContractResolver.CreateContract | TJsonDefaultContractResolver.CreateArrayContract wird eine Instanz von TJsonArrayContract erzeugt, mit der die Serialisierung arbeiten kann.