#1 2016-12-21 13:28:53

lagodny
Member
Registered: 2015-01-28
Posts: 50

Array serialization problem

There is a code:

type

  TLatLon = packed record
    Lat, Lon: Double;
  end;
  TLatLonArr = array of TLatLon;

  TLatLon1 = packed record
    Lat, Lon: Double;
    s: RawUTF8;
  end;
  TLatLonArr1 = array of TLatLon1;

...

procedure TForm1.Button1Click(Sender: TObject);
var
  a: TLatLonArr;
  a1: TLatLonArr1;
  i: Integer;
begin
  SetLength(a, 5);
  SetLength(a1, 5);
  for i := 0 to 4 do
  begin
    a[i].Lat := i;
    a[i].Lon := i;

    a1[i].Lat := i;
    a1[i].Lon := i;
  end;

  Memo1.Lines.Add(SaveJSON(a, TypeInfo(TLatLonArr)));

  Memo1.Lines.Add(SaveJSON(a1, TypeInfo(TLatLonArr1)));
end;

Tell me why
  SaveJSON(a, TypeInfo(TLatLonArr)) returns something like ["￰EAAFAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAEAAAAAAAAAAQAAAAAAAAAhAAAAAAAAACEAAAAAAAAAQQAAAAAAAABBA"]
But
  SaveJSON(a1, TypeInfo(TLatLonArr1)) returns [{"Lat":0,"Lon":0,"s":""},{"Lat":1,"Lon":1,"s":""},{"Lat":2,"Lon":2,"s":""},{"Lat":3,"Lon":3,"s":""},{"Lat":4,"Lon":4,"s":""}]

The difference is
  s: RawUTF8;

Tested in Delphi XE2

By the way custom serialization doesn't work too:

  TTLatLonArrSerializer = class
    class function ShortReader(P: PUTF8Char; var aValue; out aValid: Boolean): PUTF8Char;
    class procedure ShortWriter(const aWriter: TTextWriter; const aValue);
  end;

implementation

{ TTLatLonArrSerializer }

class function TTLatLonArrSerializer.ShortReader(P: PUTF8Char; var aValue; out aValid: Boolean): PUTF8Char;
var
  V: TLatLon absolute aValue;
begin
  aValid := false;
  result := nil;
  if (P=nil) or (P^<>'[') then
    exit;
  inc(P);

  V.Lat := GetNextItemDouble(P);
  V.Lon := GetNextItemDouble(P);

  if P=nil then
    exit;

  aValid := true;
  result := P;
end;

class procedure TTLatLonArrSerializer.ShortWriter(const aWriter: TTextWriter; const aValue);
var
  V: TLatLon absolute aValue;
begin
  aWriter.Add('["%","%"]', [V.Lat, V.Lon], twJSONEscape);
end;

initialization

  TTextWriter.RegisterCustomJSONSerializer(TypeInfo(TLatLon),
    TTLatLonArrSerializer.ShortReader, TTLatLonArrSerializer.ShortWriter);

end.

Offline

#2 2016-12-21 17:11:30

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: Array serialization problem

TLatLon has no managed field within, so it is not directly available through RTTI.

Use text definition for this type.

Offline

#3 2016-12-21 20:41:25

lagodny
Member
Registered: 2015-01-28
Posts: 50

Re: Array serialization problem

OK.
Good explanation, but why SaveJSON(a[0], TypeInfo(TLatLon)) returns {"Lat":0,"Lon":0} ?
And why does not custom serialization work?
I apologize for boring, but is it the final diagnosis? It is tempting to use the arrays of records without string fields.
Just curious.

Offline

#4 2016-12-22 08:11:00

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: Array serialization problem

I use text definition everywhere, to by-pass the RTL limitations.
Perhaps there is some potential improvement for the framework to fill such gaps, but I do not have time now.

Offline

#5 2016-12-22 10:14:37

lagodny
Member
Registered: 2015-01-28
Posts: 50

Re: Array serialization problem

Thanks for answer, but I tried to dig by myself and found something interesting:
SynCommons (line:41326)
  fElemType := PTypeInfo(aTypeInfo)^.elType;

I inspected PTypeInfo(aTypeInfo)^ , it has properties
  elType = nil
and
  elType2 = $62CA90

When I modified
  fElemType := PTypeInfo(aTypeInfo)^.elType2;
I have got the result = [{"Lat":0,"Lon":0},{"Lat":1,"Lon":1},{"Lat":2,"Lon":2},{"Lat":3,"Lon":3},{"Lat":4,"Lon":4}]

SynCommons (line:18870)
      // also unmanaged field
      elType2: PTypeInfoStored;

May be should be used elType2 for unmanaged fields, or at least in the case when elType = nil. Will it be correct?

Offline

#6 2016-12-22 12:46:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: Array serialization problem

This was as designed, to have the same serialization behavior with compilers prior to Delphi 2010, and with FPC.

Your modification would change the behavior, and break other features (like T*ObjArray support).

Offline

#7 2016-12-22 14:17:01

lagodny
Member
Registered: 2015-01-28
Posts: 50

Re: Array serialization problem

Ok. It seems like I have to follow your proposition to use text definition.
Thanks a lot.

Offline

#8 2016-12-22 15:23:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: Array serialization problem

I confess the current way of working is misleading, at least...

Offline

Board footer

Powered by FluxBB