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 );