You are not logged in.
Pages: 1
In mORMot1 I was using similar code to ObjectToJSON to serialize objects with runtime filtering on what fields should end up in the JSON.
I was doing it by using TTextWriter.OnWriteObject (the rest of the code was identical to the ObjectToJSON procedure), and returning True on any field/object that should not be serialized.
Is there a way of achieving this using mORMot2? I have failed to find a way to do so .
Offline
Is there a way of achieving this using mORMot2?
I am not sure if I understand your requirement correctly. You can do it with a custom serializer:
type
TTestObject = class(TSynPersistent)
private
FVorname: RawUtf8;
FNachname: RawUtf8;
class procedure TTestObjectWriter(pmWriter: TJsonWriter; pmData: Pointer; pmOptions: TTextWriterWriteObjectOptions);
published
property Vorname: RawUtf8
read FVorname write FVorname;
property Nachname: RawUtf8
read FNachname write FNachname;
end;
class procedure TTestObject.TTestObjectWriter(pmWriter: TJsonWriter; pmData: Pointer; pmOptions: TTextWriterWriteObjectOptions);
begin
with TTestObject(pmData) do
pmWriter.AddJsonEscape(['Vorname', Vorname, 'Nachname', Nachname]);
end;
initialization
TRttiJson.RegisterCustomSerializer(TypeInfo(TTestObject), Nil, TTestObject.TTestObjectWriter);
If you're looking for something else, I have a class TCompPropStorage in the source code for this article in the unit u_Utilities.pas.
With best regards
Thomas
Offline
Thank for recommendation!
Though I think it would require a lot of custom serializers.
Here is more information with examples: I had this following function which I called for any object class:
function TWIERestExecute.ObjectToJSON(Value: TObject; Options: TTextWriterWriteObjectOptions = [woDontStoreDefault]): RawUTF8;
var
temp: TTextWriterStackBuffer;
aTextWriter: SynCommons.TTextWriter;
begin
if Value = nil then
result := NULL_STR_VAR
else
begin
aTextWriter := DefaultTextWriterSerializer.CreateOwnedStream(temp);
try
aTextWriter.OnWriteObject := OnWriteObject;
aTextWriter.CustomOptions := aTextWriter.CustomOptions + [twoForceJSONStandard];
aTextWriter.WriteObject(Value, Options);
aTextWriter.SetText(result);
finally
aTextWriter.Free;
end;
end;
end;
And the OnWriteObject implement was as such:
function TWIERestExecute.OnWriteObject(Sender: SynCommons.TTextWriter; Value: TObject; PropInfo: pointer; Options: TTextWriterWriteObjectOptions): boolean;
begin
if ((FBasePropInfosToInclude.IndexOf(PropInfo) <> -1) or (FPropInfosToInclude.Count = 0) or (FPropInfosToInclude.IndexOf(PropInfo) <> -1)) and
(FBasePropInfosToExclude.IndexOf(PropInfo) = -1) then
result := False
else
result := True; {Will skip this property}
end;
The above class fields are just TLists, which I used as such:
FBasePropInfosToExclude := TList.Create;
FBasePropInfosToExclude.Add(GetPropInfo(TypeInfo(TWebOutputRemotable), 'ErrorCode'));
FBasePropInfosToExclude.Add(GetPropInfo(TypeInfo(TWebOutputRemotable), 'ErrorMessage'));
The client code could then define what properties it wanted to serialize, without needing a custom serializer for each class I use.
If I understand the example you sent I would need to define a custom serializer for each class that is getting serialized right?
Edit: The TLists are actually getting populated using strings received through a rest API, in the format classname.propertyname, and so it varies from call to call.
My example does not reflect that.
Last edited by AntoineGS (2023-07-24 22:44:32)
Offline
Though I think it would require a lot of custom serializers.
You can serialize the object yourself. For non-nested objects like this:
var
FPropNamesToInclude: TRawUtf8DynArray;
FPropNamesToExclude: TRawUtf8DynArray;
class procedure TTestObject.TTestObjectWriter(pmWriter: TJsonWriter; pmInstance: TObject; pmOptions: TTextWriterWriteObjectOptions);
var
value: TRttiVarData;
begin
pmWriter.Add('{');
for var run: TRttiCustomProp in Rtti.ByClass[pmInstance.ClassType].Props.List do
begin
if (FindPropName(FPropNamesToInclude, run.Name) >= 0)
and (FindPropName(FPropNamesToExclude, run.Name) < 0) then
begin
pmWriter.AddFieldName(run.Name);
run.GetValue(pmInstance, value);
pmWriter.AddVariant(Variant(value));
pmWriter.AddComma;
end;
end;
pmWriter.CancelLastComma;
pmWriter.Add('}');
end;
Then you only need to register objects.
With best regards
Thomas
Offline
Pages: 1