You are not logged in.
I think the use of regular procedures can save a lot of code
because we will need only one pair of them
for each array of ordinals or array of records
and not for each class used such arrays.
Of course, I can continue to write something like this.
procedure IntArrWriter(aObject: TObject; const aWriter: TTextWriter; const aValue);
var
v: integer absolute aValue;
begin;
aWriter.Add('%', [v], twJSONEscape);
end;
function IntArrReader(aObject: TObject; p: PUTF8Char; var aValue; out aValid: Boolean): PUTF8Char;
var
v: integer absolute aValue;
delim: AnsiChar;
begin;
aValid:=false;
Result:=nil;
if p=nil then exit;
v:=GetInteger(GetJSONField(p,p,nil,@delim));
if p=nil then exit;
dec(p); p^:=delim;
aValid:=true;
Result:=p; // ',' or ']' for last item of array
end;
var
reader: TDynArrayJSONCustomReader;
writer: TDynArrayJSONCustomWriter;
initialization
@reader:=@IntArrReader;
@writer:=@IntArrWriter;
TTextWriter.RegisterCustomJSONSerializer(TypeInfo(TIntArr), reader, writer);
Offline
Using methods allows access to an execution context via the supplied class instance.
It can be very convenient, e.g. if you need a lookup table or some read some properties during (un)serialization process.
Using such a procedure/function with a first blind object is working, and a syntaxic sugar.
You can simple define a class with static class methods instead, and still use a method-with-no-context execution. It will produce the same exact asm, just passing the class type as first parameter.
Online
Yes, I see.
Then I will use this feature as follows.
type
TDynArrayWriter= procedure(aUserInfo: pointer; const aWriter: TTextWriter; const aValue);
TDynArrayReader= function(aUserInfo: pointer; p: PUTF8Char; var aValue; out aValid: Boolean): PUTF8Char;
procedure RegisterDynArrayRW(aTypeInfo: pointer; aReader: TDynArrayReader; aWriter: TDynArrayWriter; aUserInfo: pointer= nil);
implementation
procedure RegisterDynArrayRW(aTypeInfo: pointer; aReader: TDynArrayReader; aWriter: TDynArrayWriter; aUserInfo: pointer= nil);
var
Reader, Writer: TMethod;
begin;
Reader.Code:=@aReader; Reader.Data:=aUserInfo;
Writer.Code:=@aWriter; Writer.Data:=aUserInfo;
TTextWriter.RegisterCustomJSONSerializer(aTypeInfo,
TDynArrayJSONCustomReader(Reader),
TDynArrayJSONCustomWriter(Writer));
end;
procedure Int64ArrayWriter(aUserInfo: pointer; const aWriter: TTextWriter; const aValue);
var
v: int64 absolute aValue;
begin;
aWriter.Add(v);
end;
function Int64ArrayReader(aUserInfo: pointer; p: PUTF8Char; var aValue; out aValid: Boolean): PUTF8Char;
var
v: int64 absolute aValue;
wasString: boolean;
delim: AnsiChar;
begin;
aValid:=false;
Result:=nil;
if p=nil then exit;
v:=GetInt64(GetJSONField(p,p,@wasString,@delim));
if (p=nil) or wasString then exit;
dec(p); p^:=delim;
aValid:=true;
Result:=p; // ',' or ']' for last item of array
end;
But the problem consists that I can't register some serializers with different UserData for the same type.
Offline
If two different classes have the same DynArrayTI and RecordTI,
we can use only one reader/writer pair to process these classes.
Class TI is useless.
OK, let's leave everything as is.
Anyway it isn't especially important.
Offline