Question Details

No question body available.

Tags

json jsonpath

Answers (2)

Accepted Answer Available
Accepted Answer
July 1, 2026 Score: 2 Rep: 328 Quality: High Completeness: 80%

This is a tricky one, and that online evaluator's output can be misleading. You need to keep this in mind:

  • JSONPath query always returns a list of matches, even if there’s only one.

That means if there's no match (empty result), it gives you []. If there's one match, it's returned with [1st-match], and so forth.

So, if you apply this JSONPath expression $["0"] to get the value which is associated to the key "0", you get the result like so:

[
  [
    [
      "Why are we here",
      {
        "zi": "AI Mode",
        "zf": 27,
        "zp": {
          "udm": "50"
        }
      }
    ],
    [
      "world cup standing",
      {
        "zf": 27
      }
    ],
    [
      "test",
      {
        "zf": 27,
        "zp": {
          "udm": "2"
        },
        "zi": "Images"
      }
    ]
  ]
]

Note the extra outermost [...] bracket pair is added by the evaluator because that's the standard way, as explained above. It's not from your original document.

You want to further navigate down this path by finding a sub-element so that:

  • We need to match sub-element(s) with certain element pattern, this can be down with a filter operator ?

  • Each sub-element is an array, which is denoted as a @ as "current array element".

  • From that, we wish to say: On the 2nd sub-element (based 0) of the current array element, which is @[1], I want a matched sub-element to have a key which is zp, which value in turns has a key udm, which value is "50". Hence: [?@[1].zp.udm=="50"]

  • Append that to the previous one, we get: $["0"][?@[1].zp.udm=="50"]

We get this as a result:

[
  [
    "Why are we here",
    {
      "zi": "AI Mode",
      "zf": 27,
      "zp": {
        "udm": "50"
      }
    }
  ]
]

We have already reached the goal as far as JSONPath expression can do, once again an extra bracket pair [...] is added automatically, but that's not the actual data itself. It is the responsibility of your calling program, whether if it's written in JavaScript or C# or any language, to check the result & see if it has at least 1 element in the result list. If not, it means there's no match. If yes, just get the first element from the list in your own code. You will get this as a result:

[
  "Why are we here",
  {
    "zi": "AI Mode",
    "zf": 27,
    "zp": {
      "udm": "50"
    }
  }
]

And that's exactly what you wanted.

Summary

  • JSONPath expression: $["0"][?@[1].zp.udm=="50"]
  • program should check result list length
  • if length > 0, retrieve its first element as the actual result
July 2, 2026 Score: 2 Rep: 21 Quality: Low Completeness: 100%

Answer:

Tony Chu's accepted answer is spot on with the expression $["0"][?@[1].zp.udm=="50"]. I want to expand on the underlying mechanics of why your initial attempts didn't work, as understanding this is key to mastering JSONPath's filter context.

Why Your . and .. Attempts Failed

The crucial concept here is the "current item" referenced by @ inside a filter expression.

  • When you write a filter like [? ... ], you are iterating over an array.

  • Inside that filter, the @ symbol represents each individual element of that array, one at a time.

In your data, each element of the outermost array is itself an array (e.g., ["Why are we here", {...}]). So, within the filter, @ is this entire inner array. To access its second element (the unnamed object), you must use an explicit index, @[1], because @ itself is an array, not an object. That's precisely what Tony's [?@[1].zp.udm=="50"] does.

Your attempts with @.zp.udm or @..zp.udm didn't work because:

  • . is a wildcard for object member values, not array elements.

  • .. is a recursive descent operator.
    Neither is the correct tool to navigate an array by positional index, which is what your data structure requires.

Understanding the Result Wrapping and How to Handle It in Code

A key point that often causes confusion: JSONPath always returns a list of matches, even if there's only one match or zero matches. That's why the evaluator wraps Tony's result in an extra [...].

Here's how to handle this reliably in a real-world application:

JavaScript example:


const query = 'Your JSONPath expression'; // $["0"][?@[1].zp.udm=="50"]
const resultList = jsonpath.query(data, query);

if (resultList.length > 0) { const actualMatch = resultList[0]; console.log(actualMatch); // Your desired array: ["Why are we here", {...}] } else { console.log("No match found"); }

Python example:

import jsonpath_ng

query = '$["0"][?@[1].zp.udm=="50"]' result_list = jsonpath_ng.parse(query).find(data)

if result_list: actual_match = result_list[0].value print(actual_match) # Your desired array: ["Why are we here", {...}] else: print("No match found")

Always check if the result list is non-empty before accessing the first element to avoid exceptions in your code.

Summary for Future JSONPath Challenges

When filtering based on fields inside an anonymous object that sits at a known position within an array, always use the explicit index syntax @[index] to first navigate to that object, then continue drilling down.

  • Correct: [?@[1].zp.udm=="50"]

  • Incorrect: [?@.zp.udm=="50"]

I hope this clarifies the mechanics behind the solution!