You are not logged in.
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
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
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
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
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
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
tyvm everything works fine now.
Rad Studio 12.1 Santorini
Offline