What is the correct syntax for a filter expression to query a JSON object with a specific attribute string value inside an array, using bracket notation?
I am limited to bracket notation because dot notation won't work in Delphi when there is a quote or apostrophe inside the filter expression.
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.
I've used an online JSON path evaluator against this JSON and come up with the expression result["elements"][?(@.name == 'Training Seminar - Nov 9')]
. In the online evaluator, this path works fine and returns the exact object I'm looking for. However, when I run it in Delphi I get an exception that says
EJSONPathException: Invalid index for array: ?(@.name == 'Training Seminar - Nov 9')
My question is, what is the correct syntax for a filter expression to query a JSON object with a specific attribute string value inside an array, using bracket notation?
MCVE for this as a console application, including the 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.
You can't use expressions at all, because they are not implemented. Whether in dot notation or bracket notation. Excerpt from official documentation of System.JSON.TJSONPathParser.
These operators do not support special expressions, they only support actual values (object properties or array indexes).
However in this case, it can be achieved in a slightly more complicated way.
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;