我正在解析并在Delphi XE8中抛出一个JSON结构,由于JSON结构,它给了我一个错误。如果我使用REST调试器,我可以看到网格中的数据,但如果我尝试手动获取它,我会收到错误。
这是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":""
}
]
}
我可以正确地从1级获得配对列表:S,F,D
但是如何测试数据是否是数据的匿名记录: 我试过了:
if JSO.Pairs[i].JsonString.Value = '' then
我得到一个异常EListError消息......这是正常的,因为没有与值“{”PRJCT_ID“:”7“,”PRJCT_NAME“:”Hotel La Rosiere“,”PRJCT_ADRESS“:”le plateau“关联的JSON键“}”
我的代码是
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;
我该怎么办?有人有个主意吗?
Nota:我调用匿名JSON记录设置JSON中没有的部分 我们可以说是数组“D”的成员:“D [1]”:{“PRJCT_ID”:“7”, “PRJCT_NAME”:“Hotel La Rosiere”,“PRJCT_ADRESS”:“le plateau”}我将其称为anonymouse,因为此记录集没有自己的参考密钥。
这是完整的代码:关于构建TREE的词典 - 数据访问以及Key字符串值或索引:(注意我只会“解析”节点,如果需要(Get),如果不是,它将保持存储状态一个字符串)
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;
我使用以下代码查看内容:
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;
答案 0 :(得分:1)
您没有正确访问阵列。当您找到TJSONArray
时,您将其类型转换为TJSONObject
,但数组不是对象。如果您使用as
运算符进行类型转换,则会遇到运行时错误,但您没有。
你需要做更多这样的事情:
procedure TAArray2.ExtractValues(JSO : TJSONObject);
var
i, j: integer;
pair: TJSONPair;
arr: TJSONArray;
value: TJSONvalue;
begin
for i := 0 to JSO.Count-1 do
begin
pair := JSO.Pairs[i];
value := pair.JsonValue;
if value is TJSONArray then
begin
arr := TJSONArray(value);
for j := 0 to arr.Count-1 do
begin
value := arr[j];
if value is TJSONObject then
begin
ExtractValues(TJSONObject(value));
end
else
begin
// value is not an object, do something else...
end;
end;
end
else
begin
AddItem(pair.JsonString.Value, value.Value);
end;
end;
end;
更新:JSON文档已经在树结构中。如果您尝试向用户显示该树,例如在TTreeView
中,那么您可以使用以下内容:
function TAArray2.AddJSONValueToTreeView(const Name: String; Value: TJSONValue; ParentNode: TTreeNode = nil): TTreeNode;
var
i: integer;
obj: TJSONObject;
pair: TJSONPair;
arr: TJSONArray;
begin
if ParentNode <> nil then
Result := TreeView1.Items.AddChild(ParentNode, Name);
else
Result := TreeView1.Items.Add(nil, Name);
if Value is TJSONObject then
begin
obj := TJSONObject(Value);
for i := 0 to obj.Count-1 do
begin
pair := obj.Pairs[i];
AddJSONValueToTreeView(pair.JsonString.Value, pair.JsonValue, Result);
end;
end
else if Value is TJSONArray then
begin
arr := TJSONArray(Value);
for i := 0 to arr.Count-1 do
begin
AddJSONValueToTreeView('['+IntToStr(i)+']', arr.Items[i], Result);
end;
end
else
begin
TreeView1.Items.AddChild(Result, Value.Value);
end;
end;