将过滤器表达式添加到 JSONIterator Find 函数调用

Adding a filter expression to a JSONIterator Find function call

过滤器表达式使用方括号表示法查询数组中具有特定属性字符串值的 JSON 对象的正确语法是什么?

我只能使用方括号表示法,因为当过滤器表达式中有引号或撇号时,点表示法在 Delphi 中不起作用。

Use [] to access object properties that do contain a quoting character in their name. For example, use root['child.name'] or root["child.name"] to access the child.name property of the root object.

我使用在线 JSON 路径评估器对此 JSON 进行了计算,并提出了表达式 result["elements"][?(@.name == 'Training Seminar - Nov 9')]。在在线评估器中,此路径工作正常并且 returns 正是我正在寻找的对象。但是,当我 运行 它在 Delphi 中时,我得到一个异常

EJSONPathException: Invalid index for array: ?(@.name == 'Training Seminar - Nov 9')

我的问题是,使用方括号表示法查询数组中具有特定属性字符串值的 JSON 对象的过滤器表达式的正确语法是什么?

MCVE 将此作为控制台应用程序,包括 JSON.

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Classes, System.JSON.Builders, System.JSON.Readers, System.JSON.Types;

const JsonStr = '{' +
'   "result":{     ' +
'      "elements":[   ' +
'         {              ' +
'            "id":"ML_1HMloeUjEFgKaC9",' +
'            "name":"Utilization Survey",' +
'         },' +
'         {' +
'            "id":"ML_1zQjGtGXFPkEo6N",' +
'            "name":"Training Seminar - Nov 9",' +
'         }' +
'      ]' +
'   },' +
'   "meta":{' +
'      "httpStatus":"200 - OK",' +
'      "requestId":"ef2afd6e-3fd9-4fdf-a8fe-c935c147a0af"' +
'   }' +
'}';

procedure RunIt;
var Reader : TJsonTextReader;
  Iterator : TJsonIterator;
  StringReader : TStringReader;
  Found : Boolean;
begin
  StringReader := TStringReader.Create(JsonStr);
  Reader := TJsonTextReader.Create(StringReader);
  Iterator := TJsonIterator.Create(Reader);
  try
    Found := Iterator.Find('result["elements"][?(@.name == ''Training Seminar - Nov 9'')]');
    //The value of Found is false or an exception is raised because of bad syntax in the filter expression
    WriteLn(BoolToStr(Found));
    ReadLn;
  finally
    Iterator.Free;
    Reader.Free;
    StringReader.Free;
  end;
end;

begin
  try
    RunIt;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      Readln;
    end
  end;
end.

你根本不能使用表达式,因为它们没有实现。无论是点符号还是括号符号。摘自System.JSON.TJSONPathParser.

的官方文档

These operators do not support special expressions, they only support actual values (object properties or array indexes).

不过在这种情况下,可以通过稍微复杂一点的方式来实现。

procedure RunIt;
var
  lJSON, lValue, lName: TJSONValue;
  lFound : Boolean;
begin
  lFound := False;
  lJSON := TJSONObject.ParseJSONValue(JsonStr);
  if Assigned(lJSON) then
  try
    if lJSON.TryGetValue('result.elements', lValue) and (lValue is TJSONArray) then
    begin
      for lValue in TJSONArray(lValue) do
      begin
        lFound := lValue.TryGetValue('name', lName) and (lName.Value = 'Training Seminar - Nov 9');
        if lFound then
          Break;
      end;
    end;
  finally
    lJSON.Free;
  end;
  WriteLn(BoolToStr(lFound));
  ReadLn;
end;