You are not logged in.
I had a code with mORMot1 like:
TTextWriter.RegisterCustomJSONSerializer(TypeInfo(TItems), @ReadItem, nil);
and
function TItemReader.ReadItem(P: PUTF8Char; var AValue; out AValid: boolean): PUTF8Char;
var
V: TObject absolute AValue;
OldP, S: PUTF8Char;
SP: RawUTF8;
L: integer;
begin
AValid := False;
Result := nil;
if P = nil then
Exit;
OldP := P;
P := JsonObjectItem(P, 'CustomClass');
if P = nil then
raise Exception.Create('Invalid Item');
JSONRetrieveStringField(P, S, L, False);
SetString(SP, S, L);
case SP of
'ItemA': V := TItemA.Create;
'ItemB': V := TItemB.Create;
else
raise Exception.Create('Unknown Item: ' + SP);
end;
AValid := True;
Result := JSONToObject(AValue, OldP, AValid, nil, JSONTOOBJECT_TOLERANTOPTIONS);
end;
and now with mORMot2, I can not convert it.
I thought I should do this but it leads to unknown errors.
function TItemReader.ReadItem(P: PUTF8Char; var AValue; out AValid: boolean): PUTF8Char;
var
V: TObject absolute AValue;
OldP, S: PUTF8Char;
SP: RawUTF8;
L: integer;
begin
AValid := False;
Result := nil;
P := Context.Json;
OldP := P;
P := JsonObjectItem(P, 'CustomClass');
if P = nil then
raise Exception.Create('Invalid Item');
JSONRetrieveStringField(P, S, L, False);
SetString(SP, S, L);
case SP of
'ItemA': V := TItemA.Create;
'ItemB': V := TItemB.Create;
else
raise Exception.Create('Unknown Item: ' + SP);
end;
AValid := True;
Context.Json := JSONToObject(Instance, Context.Json, Context.Valid, nil, JSONTOOBJECT_TOLERANTOPTIONS);
end;
What is the correct way to unserializing and array of classes?
Note: I can not use ParseNewObject, as the CustomClass property may not be the first properties and some other custom needs.
Offline
Here is my response to my question. I do not know if this is the best option though.
procedure TItemReader.ReadItem(var Context: TJsonParserContext; Data: pointer);
var
S: PUTF8Char;
SP: RawUTF8;
L: integer;
C: TItemClass;
Instance: TObject;
begin
Result := nil;
P := Context.Json;
OldP := P;
P := JsonObjectItem(P, 'CustomClass');
if P = nil then
raise Exception.Create('Invalid Item');
JSONRetrieveStringField(P, S, L, False);
SetString(SP, S, L);
case SP of
'ItemA': C := TItemA;
'ItemB': C := TItemB;
else
raise Exception.Create('Unknown Item: ' + SP);
end;
Context.Info := Rtti.RegisterClass(C);
Instance := TRttiJson(Context.Info).ParseNewInstance(Context);
end;
And register it like this:
TRttiJson.RegisterCustomSerializer(TypeInfo(TItem), @ReadItem, nil);
Last edited by okoba (2022-02-19 20:57:09)
Offline
It was a copy and paste issue, fixed it.
Is the style of the solution correct? Registering the class and using ParseNewInstance?
Offline
Shouldn't it be called that?
TRttiJson.RegisterCustomSerializer(TypeInfo(TItem), TItemReader.ReadItem, nil);
Examples can be found in the test units for mORMot2.
Maybe it's better to first describe what you actually want to do (what the data structure you want to serialize looks like) and not how you do it.
With best regards
Thomas
Offline