#1 2014-04-30 13:54:35

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 516

define array of RawUTF8 for RegisterCustomJSONSerializerFromText

Hi, given the following packed record:

  TTestComponentsJSON = packed record
    name1, name2 : RawUTF8;
    types : array of RawUTF8;
  end;

  TTest2JSON = packed record
    test : array of TTestComponentsJSON;
  end;

i have Problems to define the rtti - Text Const for the array of RawUTF8 !

__TTestJSON = 'test [name1 RawUTF8 name2 RawUTF8 types [array RawUTF8]]';

My Question: How i have to specify the array of RawUTF8 ?


Rad Studio 12.1 Santorini

Offline

#2 2014-04-30 23:00:59

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

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

Array of rawutf8

As stated by the docs

Offline

#3 2014-05-03 10:02:07

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 516

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

Thank you the Preparation now works fine,

but in ReadOneLevel / ParseValue is an Error in parsing the array.
EndElement is set to ] not to } as expected from the parser after parsing the String array

"types" : [ "testtype_1" ]

the Parser exits with error.

Example :

{
   "test" : [
            {
               "name1" : "name1_1",
               "name2" : "name2_1",
               "types" : [ "testtype_1" ]
            },
            {
               "name1" : "name1_2",
               "name2" : "name2_2",
               "types" : [ "testtype_2" ]
            }
   ]
}

Rad Studio 12.1 Santorini

Offline

#4 2014-05-03 11:06:40

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

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

I just updated the regression tests to check for this record type:

  TTestCustomJSONArraySimple = packed record
    A,B: Int64;
    C: array of TGUID;
    D: RawUTF8;
    E: array of record
      F: RawUTF8;
      G: array of RawUTF8;
    end;
  end;

And no problem when parsing '{"a":1,"b":2,"c":["C9A646D3-9C61-4CB7-BFCD-EE2522C8F633",'+
    '"3F2504E0-4F89-11D3-9A0C-0305E82C3301"],"d":"4","e":[{"f":"f","g":["g1"]}]}' i.e. with a dynamic array of RawUTF8.

Are you sure you have defined your record as such:

__TTestJSON = 'test [name1,name2 RawUTF8 types array of RawUTF8]';

Offline

#5 2014-05-03 11:17:47

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 516

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

I think i have to provide my original piece of code to find the error:

i try to decode google geocode - Data.

This is my Structure

  TGoogleAdressComponentsJSON = packed record
    long_name, short_name : RawUTF8;
    types : array of RawUTF8;
  end;
  TGoogleLocationJSON = packed record
    lat, lng : double;
  end;
  TGoogleViewportJSON = packed record
    northeast : TGoogleLocationJSON;
    southwest : TGoogleLocationJSON;
  end;
  TGoogleGeometryJSON = packed record
    location : TGoogleLocationJSON;
    location_type : RawUTF8;
    viewport : TGoogleViewportJSON;
  end;
  TGoogleAdressJSON = packed record
    addess_components : array of TGoogleAdressComponentsJSON;
    formatted_address : RawUTF8;
    geometry : TGoogleGeometryJSON;
    partial_match : boolean;
    types : array of RawUTF8;
  end;
  TGoogleGeoCodeJSON = packed record
    results : array of TGoogleAdressJSON;
    status : RawUTF8;
  end;

const
  __TGoogleGeocodeJSON = 'results ['+
                           'address_components [long_name RawUTF8 short_name RawUTF8 types array of RawUTF8] '+
                           'formatted_address RawUTF8 ' +
                           'geometry {location {lat, lng double} '+
                           'location_type RawUTF8 '+
                           'viewport {northeast {lat, lng double} southwest {lat, lng double}}} '+
                           'partial_match boolean '+
                           'types array of RawUTF8'+
                         '] '+
                         'status RawUTF8';

I modified ProcessValue in SymCommons.pas

    ptArray: begin
      if P^<>'[' then
        exit; // we expect a true array here
      repeat inc(P) until P^<>' ';
      // allocate nested array at once
      ArrayLen := JSONArrayCount(P);
      if ArrayLen<0 then
        exit; // invalid JSON array
      Prop.AllocateNestedArray(PPtrUInt(Data)^,ArrayLen);
      // read array content
      if ArrayLen>0 then begin
        DynArray := PPointer(Data)^;
        for j := 1 to ArrayLen do begin
          {$ifdef ALIGNCUSTOMREC}
          BegDynArray := DynArray; // for 8 byte alignment of arrays
          {$endif}
          if Prop.NestedProperty[0].PropertyName='' then begin
            // array of integer/string/array/custom...
            if not ProcessValue(Prop.NestedProperty[0],P,DynArray) or (P=nil) then
              exit;
          end else // array of record
          if not Prop.ReadOneLevel(P,DynArray,Options) or (P=nil) then
            exit;
          {$ifdef ALIGNCUSTOMREC}
          inc(DynArray,(PtrUInt(DynArray)-PtrUInt(BegDynArray)) and 7);
          {$endif}
          if P^=',' then
            inc(P);
        end;
      end;
      if P=nil then
        exit;
      P := GotoNextNotSpace(P);
>> INSERTED
      if (EndOfObject = ']') and (P^='}') then begin
        EndOfObject := '}';
        inc(P);
      end else 
<< INSERTED
      if (P^=']') or (Prop.NestedProperty[0].PropertyName<>'') then begin
        if (P^<>']') then
          exit; // we expect a true array here
        repeat inc(P) until not(P^ in [#1..' ']);
        EndOfObject := P^;
        if P^<>#0 then //if P^=',' then
          inc(P);
      end;
    end;

and the parser work now.

(Now its working fine !)

Last edited by itSDS (2014-05-03 11:39:05)


Rad Studio 12.1 Santorini

Offline

#6 2014-05-03 11:44:32

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 516

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

One more Question concerning this task.

Is it possible to interpret the Result from google directly with mORMot. Actual i use Indy to retrieve the http - Stream

        Stream := TStringStream.Create(res);
        try
          Str := TIDUri.UrlEncode(STR_WEB + AAdresse + '&sensor=false');
          IdHTTP.Get(Str, Stream);

          Infos := Stream.DataString;
          U := AnsiString(Infos);

          JSON := RecordLoadJSON(Cache,@U[1],TypeInfo(TGoogleGeoCodeJSON));

          if assigned(JSON) then try

Rad Studio 12.1 Santorini

Offline

#7 2014-05-03 12:39:44

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

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

There was indeed an issue in our code!

I've fixed it in another way, which seems more generic/natural to me.
See http://synopse.info/fossil/info/a4fd7c934e


You can retrieve any HTTP content directly with the SynCrtSock unit.

There are several classes to handle a client connection.

Offline

#8 2014-05-05 07:26:01

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 516

Re: define array of RawUTF8 for RegisterCustomJSONSerializerFromText

tyvm everything works fine now.


Rad Studio 12.1 Santorini

Offline

Board footer

Powered by FluxBB