使用TJsonDataObjects按路径删除JSON记录及获取节点路径问询
TJsonDataObjects 路径操作问题解决方案
1. 按路径删除JSON节点的实现
你当前的截断路径找父节点的思路是无需修改组件源码的最优实现,只需要把逻辑封装成通用函数即可达到和原生DeletePath方法一致的使用体验:
- 拆分目标路径为父路径和末端键/索引,例如路径
Level1.Level2.Level3拆分后父路径为Level1.Level2,末端键为Level3 - 通过路径获取父节点实例,判断父节点是对象类型还是数组类型
- 对应调用对象的
Delete(键名)方法或数组的Delete(索引)方法完成删除
封装示例代码如下:
procedure DeleteJsonPath(Json: TJsonDataObject; const Path: string); var LastDotPos: Integer; ParentPath, ChildKey: string; ParentNode: TJsonValue; ParentObj: TJsonObject; ParentArr: TJsonArray; ChildIdx: Integer; begin LastDotPos := LastDelimiter('.', Path); // 根节点不支持删除,直接退出 if LastDotPos = 0 then Exit; ParentPath := Copy(Path, 1, LastDotPos - 1); ChildKey := Copy(Path, LastDotPos + 1, MaxInt); ParentNode := Json.Path[ParentPath]; if not Assigned(ParentNode) then Exit; if ParentNode is TJsonObject then begin ParentObj := TJsonObject(ParentNode); if ParentObj.Contains(ChildKey) then ParentObj.Delete(ChildKey); end else if ParentNode is TJsonArray then begin ParentArr := TJsonArray(ParentNode); if TryStrToInt(ChildKey, ChildIdx) and (ChildIdx >= 0) and (ChildIdx < ParentArr.Count) then ParentArr.Delete(ChildIdx); end; end;
封装完成后直接调用DeleteJsonPath(Json, 'Level1.Level2.Level3')即可实现按路径删除节点。
2. 从节点反向获取JsonPath的实现
组件本身没有内置反向路径拼接能力,你可以利用TJsonValue自带的Owner属性格式遍历到根节点,逐层拼接路径,生成的路径格式和组件原生Path属性完全兼容,比解析JSON时手动拼接的维护成本更低:
function GetJsonNodePath(Node: TJsonValue): string; var CurrentNode: TJsonValue; ParentNode: TJsonValue; ParentObj: TJsonObject; ParentArr: TJsonArray; Segment: string; i: Integer; begin Result := ''; CurrentNode := Node; while Assigned(CurrentNode.Owner) do begin ParentNode := CurrentNode.Owner; Segment := ''; if ParentNode is TJsonObject then begin ParentObj := TJsonObject(ParentNode); for i := 0 to ParentObj.Count - 1 do begin if ParentObj.Values[i] = CurrentNode then begin Segment := ParentObj.Names[i]; Break; end; end; end else if ParentNode is TJsonArray then begin ParentArr := TJsonArray(ParentNode); for i := 0 to ParentArr.Count - 1 do begin if ParentArr.Items[i] = CurrentNode then begin Segment := IntToStr(i); Break; end; end; end; if Segment = '' then Break; if Result = '' then Result := Segment else Result := Segment + '.' + Result; CurrentNode := ParentNode; end; end;
调用该方法传入任意JSON节点实例,即可返回标准点分隔格式的JsonPath字符串,不需要手动维护路径拼接规则。
内容的提问来源于stack exchange,提问作者Bill F
相关产品推荐
相关产品推荐

