I m parsing and go threw a JSON structure, in Delphi XE8, and it gives me an error because of the JSON Structure. if i use the REST Debugger i can see the data in the grid but if i try to get it manually i get an error.
here is the JSON :
{
"S":1,
"U":"2898",
"F":[],
"D":[
{
"PRJCT_ID":"7",
"PRJCT_NAME":"Hotel La Rosiere",
"PRJCT_ADRESS":"le plateau"
},
{
"PRJCT_ID":"8",
"PRJCT_NAME":"Hotel Delux",
"PRJCT_ADRESS":"Centre Maison"
},
{
"PRJCT_ID":"9",
"PRJCT_NAME":"villedieu",
"PRJCT_ADRESS":""
}
]
}
I can get the Pair list from level 1 properly : S, F, D
But how can i test if the data is an anonymous record of data : i tried :
if JSO.Pairs[i].JsonString.Value = '' then
I get an Exception EListError Message... which is normal because no JSON Key associated for the value "{"PRJCT_ID":"7","PRJCT_NAME":"Hotel La Rosiere","PRJCT_ADRESS":"le plateau"}"
My code is
procedure TAArray2.ExtractValues(JSO : TJsonObject);
var
i : integer;
begin
try
i := 0;
while (i < JSO.Count) do
begin
if JSO.Pairs[i].JsonValue is TJSONArray then // array of values "Key":[{"Key":"Value","Key":"Value"},{"Key":"Value","Key":"Value"}]
begin
AddItem(JSO.Pairs[i].JsonString.Value, '', TJSonObject(JSO.Pairs[i].JsonValue)); // recursive call ExtractValues(TJSonObject(JSO.Pairs[i].JsonValue))
end
else if JSO.Pairs[i].JsonString.Value = '' then // ERROR HERE : anonymous key : {"Key":"Value","Key":"Value"},{"Key":"Value","Key":"Value"}
begin
AddItem(i, JSO.Pairs[i].JsonValue.Value);
end
else // standard creation : "Key":"Value"
begin
AddItem(JSO.Pairs[i].JsonString.Value, JSO.Pairs[i].JsonValue.Value);
end;
inc(i);
end;
finally
end;
end;
How can i do it ? Does anyone get an idea ?
Nota : i call anonymous JSON Record Set the portion of JSON that don't is member of Array "D" like we could say : "D[1]":{ "PRJCT_ID":"7", "PRJCT_NAME":"Hotel La Rosiere", "PRJCT_ADRESS":"le plateau"} i call it anonymouse because this record set doesn't have his own Reference Key.
Here is the full code : about building a dictionnary of TREE - data accessing as well as Key string value or index : (Note i will only "Parse" the node if needed (Get), if not it will stay stored like a string)
unit Unit3;
interface
uses
Classes, System.SysUtils, System.Types, REST.Types, System.JSON, Data.Bind.Components,
System.RegularExpressions, System.Variants,
Generics.Collections;
type
TAArray2 = class;
PTRec=^TRec;
TRec = class
public
Key : Variant;
isRequired : boolean;
Value : Variant;
OldValue : Variant;
JSON : string;
JSO : TJSonObject;
Items : TAArray2;
procedure Add(Key : Variant ; Value: TRec);
end;
TAArray2 = class(TDictionary<Variant, TRec>)
private
function Get(Index: variant): TRec;
procedure ExtractValues(JSO : TJsonObject);
public
procedure AddItem(Key: Variant; Value: Variant ; JSOnObject : TJSOnObject = nil);
procedure ExtractFromJSON(JSonString: string ; RootElement : string = '');
property Items[Cle : Variant]: TRec read Get; default;
end;
implementation
procedure TRec.Add(Key : Variant ; Value: TRec);
begin
if not(assigned(items)) then
self.Items := TAArray2.Create;
Items.Add( Key, Value);
end;
procedure TAArray2.AddItem(Key : Variant ; Value: Variant ; JSOnObject : TJSOnObject = nil);
var
LocalRec : TRec;
begin
LocalRec := Get(Key);
if assigned(LocalRec) then
begin
LocalRec.Key := Key;
LocalRec.Value := Value;
LocalRec.JSO := JSOnObject;
end
else
begin
LocalRec := TRec.Create;
LocalRec.Value := Value;
LocalRec.Key := Key;
LocalRec.JSO := JSOnObject;
inherited Add( Key, LocalRec);
end;
end;
function TAArray2.Get(Index: Variant): TRec;
var
LocalRec : TRec;
begin
if self.ContainsKey(Index) then
begin
LocalRec := inherited items[Index];
if (LocalRec.JSON <> '') or (LocalRec.JSO <> nil) then
begin
LocalRec.Items := TAArray2.Create;
// ExtractValues(JSO);
end;
Result := LocalRec;
end
else
begin
result := nil;
end;
end;
// *****************************************************************************
//
// *****************************************************************************
procedure TAArray2.ExtractFromJSON(JSonString: string ; RootElement : string = '');
var
JSO : TJsonObject;
JSP : TJSonPair;
begin
try
JSO := TJSOnObject.ParseJSONValue(JSonString) as TJSONObject;
try
if (RootElement <> '') then
begin
JSP := JSO.Get(RootElement);
if not(JSP.Null) then
begin
ExtractValues(TJSonObject(JSP.JsonValue));
end;
end
else if Not(JSO.Null) then
begin
ExtractValues(JSO);
end;
finally
JSO.Free();
end;
except
on E:Exception do showmessage('Data Structure Error');
end;
end;
I view the content with this code :
procedure TForm1.ShowAssocArray2(AAA : TAArray2 ; Level : integer);
var
i : Integer;
s : string;
MyRec : TRec;
begin
s := DupeString(' ',Level * 4);
for MyRec in AAA.Values Do
begin
memo2.Lines.Add(s + string(MyRec.Key) + ' = ' + string(MyRec.Value) + ' (' + string(MyRec.JSON) + ')'); // Error Here
AAA[MyRec.Key];
if assigned(MyRec.Items) then
begin
if MyRec.Items.Count > 0 then
ShowAssocArray2(MyRec.items, Level + 1); // recursive for childrens
end;
end;
end;
procedure TForm1.Button5Click(Sender: TObject);
var
MyList: TAArray2;
MyRec, MyRec2 : TRec;
i: Integer;
begin
MyList := TAArray2.Create;
MyList.ExtractFromJSON(Memo1.Lines.Text);
ShowAssocArray2(MyList, 0);
end;