示例-QJson中结点的查找与遍历方法小结

1、查找结点

QJson提供了一组函数来查找某一个结点,我们在下面来分别看一下:

function ItemByName(AName: QStringW): TQJson; overload;
function ItemByName(const AName: QStringW; AList: TQJsonItemList;ANest: Boolean = False): Integer; overload;
function ItemByRegex(const ARegex: QStringW; AList: TQJsonItemList;ANest: Boolean = False): Integer; overload;
function ItemByPath(APath: QStringW): TQJson;
function IndexOf(const AName: QStringW): Integer;
function FindIf(const ATag: Pointer; ANest: Boolean;AFilter: TQJsonFilterEventA): TQJson;
function FindIf(const ATag: Pointer; ANest: Boolean;AFilter: TQJsonFilterEvent): TQJson; overload;

(1)此函数用于在当前结点下查找指定名称的子结点,如果指不到,返回NIL/NULL。如果要确保结点存在,用ForcePath来代替此函数。

AItem:=AJson.ItemByName('MySubNode');
if Assigned(AItem) then
   ...
else
   ...

(2)此函数用于在当前结点下查找指定名称的子结点,并将找到的结点放到AList这个列表中。ANest参数指定了是否递归查找子结点。返回的是找到的结点总数。

var
  AList:TQJsonItemList;
  AJson:TQJson;
  I:Integer;
begin
AList:=TQJsonItemList.Create;
AJson:=TQJson.Create;
...
if AJson.ItemByName('Name',AList,True) then
   begin
   for I:=0 to AList.Count-1 do
      ...
   end;
...
FreeAndNil(AList);
FreeAndNil(AJson);
end;

(3)此函数用于按正则表达式查找符合要求的子结点,并将找到的结点放到AList中这个列表中。ANest参数指定了是否递归查找子结点。返回的是找到的结点总数。

如查找所有以_+数字命名的结点(类似于_0001,_0002这种形式的结点):

var
  AList:TQJsonItemList;
  AJson:TQJson;
  I:Integer;
begin
AList:=TQJsonItemList.Create;
AJson:=TQJson.Create;
...
if AJson.ItemByRegex('_\d+',AList,True) then
   begin
   for I:=0 to AList.Count-1 do
      ...
   end;
...
FreeAndNil(AList);
FreeAndNil(AJson);
end;

(4)此函数按照路径查找指定名称的子结点,由于 “.” 、 “/” 、 “\” 被当做路径分隔符,而 “[]” 被当做数组分隔符,因此,不能在结点名称中包含上述字符。如果指定的路径不存在,返回NIL/NULL。在路径中,数组分隔符适用于对象和数组类型的结点,如果是多层结构,会被当做多维数组来处理。如“a[1][2]”,表示取结点名为a下的第2个子结点的第3个子结点。

AItem:=AJson.ItemByPath('a.b.c[0].d');
if Assigned(AItem) then
  ...
else
  ...

(5)IndexOf函数和ItemByName类似,不同的是IndexOf返回对应结点的索引,如果未找到返回-1。

I:=AJson.IndexOf('Name');
if I<>-1 then
  begin
  AItem:=AJson[I];
  ...
  end;
...

(6)和(7)都是由用户提供特定的过滤规则来查找指定的结点,不同的是(6)为匿名函数版本,而(7)是普通类成员函数版本,下面的例子演示了如何使用匿名函数来过滤。

AItem:=AJson.FindIf(nil,true,procedure(ASender, AItem: TQJson;var Accept: Boolean; ATag: Pointer)
  begin
  if AItem.Name='Name' then
    Accept:=True
  else
    ...
  end);
if Assigned(AItem) then  
  ...

2、遍历结点

TQJson的每个结点的Count属性记录了总的结点数,Items属性用于返回每个子结点。在结点类型是jdtArray(数组)或jdtObject(对象)时,可以通过最简单的循环来遍历每一个子结点。

var
  AJson,AItem:TQJson;
  I:Integer;
begin
...
for I:=0 to AJson.Count-1 do
  begin
  AItem:=AJson[I];
  ...//AItem就是AJson的第I个成员
  end;
...
end;

另外,QJson 提供了 for..in 语法的支持,所以更简单的语法可以是:

var
  AJson,AItem:TQJson;
begin
...
for AItem in AJson do
  begin
  ...//编码对AItem进行处理
  end;
...
end;

要递归遍历每一个子结点,可以用FindIf方法,只不过Accept参数永远返回False即可(示例为匿名函数版本)。如:

AJson.FindIf(nil,True,
procedure(ASender, AItem: TQJson;var Accept: Boolean; ATag: Pointer)
begin
//对AItem进行处理
end
);

 

分享到: