You are not logged in.
I've faced some problem with deserialization JSON, which has a dynamic array of floating-point values inside one of the json-objects.
My JSON has a very complicated structure, but I'll provide here a simple example, showing my trouble.
TJSONArrayOfFloat = array of double;
TJSONObjectWithArray = class(TSynPersistent)
private
FArrayOfFloat: TJSONArrayOfFloat;
published
property ArrayOfFloat: TJSONArrayOfFloat read FArrayOfFloat;
end;
...
procedure TForm1.FormShow(Sender: TObject);
var
i: integer;
LJSON: RawUTF8;
LObject: TJSONObjectWithArray;
LDeserResult: boolean;
LResult: string;
begin
LJSON := StringToUTF8
('{"arrayoffloat": [10.387747, 59.377930, 11.388159, 69.377976, 12.388261, 79.377988]}');
LObject := TJSONObjectWithArray.Create;
JSONToObject(LObject, pointer(LJSON), LDeserResult);
if LDeserResult then
begin
LResult := 'Array: ';
for i := 0 to High(LObject.ArrayOfFloat) do
LResult := LResult + ' ' + FloatToStr(LObject.ArrayOfFloat[i]);
end
else
LResult := 'Deserialization error!';
FreeAndNil(LObject);
Memo1.Text := LResult;
end;
The result values are nearby 0:
Array: 4,94065645841247E-323 2,91498731046335E-322 5,43472210425371E-323 3,4090529563046E-322 5,92878775009496E-323 3,90311860214585E-322
The same result I get with type single (with lower precision).
But if I use integer dynamic array JSONToObject works fine:
TJSONArrayOfFloat = array of integer;
Array: 10 59 11 69 12 79
Delphi 10.3.1 64. Also checked this code with FPC but no luck.
Offline
What is the LObject content?
LObject is just:
LObject := TJSONObjectWithArray.Create;
The class is:
TJSONObjectWithArray = class(TSynPersistent)
private
FArrayOfFloat: TJSONArrayOfFloat;
published
property ArrayOfFloat: TJSONArrayOfFloat read FArrayOfFloat;
end;
Or maybe I misunderstood your question... Can you specify, please, what do you mean?
Offline
ah, thanks, it is pretty much the same as printed in LResult:
((4,94065645841247e-323, 2,91498731046335e-322, 5,43472210425371e-323, 3,4090529563046e-322, 5,92878775009496e-323, 3,90311860214585e-322))
couldn't find ability to post a screen - the value of LObject is copied from local variables watch list
Last edited by Vitaly (2019-07-17 15:48:02)
Offline
OK the problem is in TDynArray.ToKnownType.
It recognizes only exact types, like TDoubleDynArray.
So your TJSONArrayOfFloat is not recognized, then the value is handled as an array of integers (djInt64), resulting in the wrong values.
In order to have proper serialization, you need to use a TDoubleDynArray published property...
I can't find something more versatile, since the RTTI doesn't store any type information within TypeInfo(TJSONArrayOfFloat) for its elements.
Offline