You are not logged in.
Pages: 1
Hi,
It seems RegisterCustomSerializerFieldNames has a bug when I use more than one custom field name for more than one class.
The second register will override the first one and it is odd because they are different classes.
I can't use record serialization because inheritance is a need.
program project1;
uses
SynCommons,
mORMot;
type
{ TBaseClass }
TBaseClass = class(TSynAutoCreateFields)
private
fName: string;
published
property Name: string read fName write fName;
end;
{ TClass1 }
TClass1 = class(TBaseClass)
private
ftype_: string;
published
property type_: string read ftype_ write ftype_;
end;
{ TClass2 }
TClass2 = class(TBaseClass)
private
fclass_: string;
published
property class_: string read fclass_ write fclass_;
end;
{ TTestClass }
TTestClass = class(TSynAutoCreateFields)
private
fCount: integer;
fObject1: TClass1;
fObject2: TClass2;
published
property Count: integer read fCount write fCount;
property Object1: TClass1 read fObject1;
property Object2: TClass2 read fObject2;
end;
var
JsonString: RawUTF8;
Obj: TTestClass;
begin
TJSONSerializer.RegisterCustomSerializerFieldNames(TClass1, ['type_'], ['type']);
TJSONSerializer.RegisterCustomSerializerFieldNames(TClass2, ['class_'], ['class']);
JsonString := '{"Count":2,"Object1":{"Name":"C1","type_":"TYPE"},"Object2":{"Name":"C2","class_":"CLASS"}}';
Obj := TTestClass.Create;
WriteLn(ObjectLoadJSON(Obj, JsonString, nil, JSONTOOBJECT_TOLERANTOPTIONS));
WriteLn(ObjectToJSON(Obj, [woHumanReadable]));
Obj.Free;
ReadLn;
end.
Offline
Hi mohsenti
In the help of the function it says :
note that any inherited classes will be serialized as the parent class
.....................................................
// - note that any inherited classes will be serialized as the parent class
// - this method is thread-safe, but should be called before any serialization
class procedure RegisterCustomSerializerFieldNames(aClass: TClass;
const aClassFields, aJsonFields: array of ShortString);
I think this mean that your last TJSONSerializer.RegisterCustomSerializerFieldNames only applied.
I noticed also that JsonString content in your example is not valid since you called RegisterCustomSerializerFieldNames
TJSONSerializer.RegisterCustomSerializerFieldNames(TClass1, ['type_'], ['type']);
TJSONSerializer.RegisterCustomSerializerFieldNames(TClass2, ['class_'], ['class']);
JsonString := '{"Count":2,"Object1":{"Name":"C1","type_":"TYPE"},"Object2":{"Name":"C2","class_":"CLASS"}}';
//It must be
TJSONSerializer.RegisterCustomSerializerFieldNames(TClass1, ['type_'], ['type']);
TJSONSerializer.RegisterCustomSerializerFieldNames(TClass2, ['class_'], ['class']);
JsonString := '{"Count":2,"Object1":{"Name":"C1","type":"TYPE"},"Object2":{"Name":"C2","class":"CLASS"}}';
I hope ab, can find some time to implement it.
Last edited by Ehab (2018-11-21 04:41:32)
Offline
Thank you Ehab.
Yes you are right about the JSON, but the problem is still there.
TClass1 and TClass2 are inherited from same class but I checked with different classes that inherited from TSynAutoCreateFields and RegisterCustomSerializerFieldNames will use only the last custom serializer.
@ab , can you validate this?
Offline
I think you need to report a bug to @ab
Offline
Yes, so I will wait for him to validate my findings.
Offline
@ab I found the bug, it was because of pointers.
I solved it temporarily.
@@ -49046,7 +49046,7 @@ type
Reader: TJSONSerializerCustomReader;
Writer: TJSONSerializerCustomWriter;
Props: PPropInfoDynArray;
- Fields: PShortStringDynArray; // match Props[] order
+ Fields: TShortStringDynArray; // match Props[] order
Kind: TJSONObject;
end;
TJSONCustomParsers = array of TJSONCustomParser;
@@ -49136,7 +49136,7 @@ var i: integer;
begin
if Parser^.Props<>nil then begin // search from RegisterCustomSerializerFieldNames()
for i := 0 to length(Parser^.Fields)-1 do
- if IdemPropNameU(Parser^.Fields[i]^,PropName,PropNameLen) then begin
+ if IdemPropNameU(Parser^.Fields[i],PropName,PropNameLen) then begin
result := Parser^.Props[i];
exit;
end;
@@ -49148,7 +49148,7 @@ end;
class procedure TJSONSerializer.RegisterCustomSerializerFieldNames(aClass: TClass;
const aClassFields, aJsonFields: array of ShortString);
var prop: PPropInfoDynArray;
- field: PShortStringDynArray;
+ field: TShortStringDynArray;
n,p,f: integer;
found: boolean;
parser: PJSONCustomParser;
@@ -49167,7 +49167,7 @@ begin
for f := 0 to high(aClassFields) do // check customized field name
if IdemPropName(prop[p].Name,aClassFields[f]) then begin
if aJsonFields[f]<>'' then begin // '' to ignore this property
- field[n] := @aJsonFields[f];
+ field[n] := aJsonFields[f];
prop[n] := prop[p];
inc(n);
end;
@@ -49175,7 +49175,7 @@ begin
break;
end;
if not found then begin // default serialization of published property
- field[n] := @prop[p].Name;
+ field[n] := prop[p].Name;
prop[n] := prop[p];
inc(n);
end;
@@ -52475,7 +52475,7 @@ begin
raise EParsingException.CreateUTF8('%.WriteObject woDontStoreInherited '+
'after RegisterCustomSerializerFieldNames(%)', [self,aClassType]) else
for i := 0 to length(parser^.Props)-1 do begin
- CustomPropName := parser^.Fields[i];
+ CustomPropName := @parser^.Fields[i];
WriteProp(parser^.Props[i]);
end;
end else
Last edited by mohsenti (2018-12-02 16:12:25)
Offline
Thanks a lot for the feedback!
Please check https://synopse.info/fossil/info/d513678b44
Offline
Thanks you very much ab.
Can I ask why TShort63?
Offline
Great, Thanks.
Offline
Pages: 1