jmespath: how to search a dict of dict structure

2k Views Asked by At

There's an example of search in the tutorial going:

{
  "machines": [
    {"name": "a", "state": "running"},
    {"name": "b", "state": "stopped"},
    {"name": "b", "state": "running"}
  ]
}
In [68]: jmespath.search("machines[?state=='running'].name",p)
Out[68]: ['a', 'b']

However, my structure uses a dictionary rather than a list, e.g.:

In [64]: q={
    ...:   "machines": {
    ...:     "m1":     {"name": "a", "state": "running"},
    ...:     "m2":     {"name": "b", "state": "stopped"},
    ...:     "m3":     {"name": "c", "state": "running"}
    ...:     }
    ...:     }

My different attempts to parse this have failed:

In [65]: jmespath.search("machines[?state=='running'].name",q)
# no output
In [66]: jmespath.search("machines.*[?state=='running'].name",q)
Out[66]: []

In [67]: jmespath.search("machines[*][?state=='running'].name",q)
# no output

How can I perform this search?

1

There are 1 best solutions below

0
On BEST ANSWER

You can use a * wildcard expression to select all values from a hash:

>>> jmespath.search("machines.*", q)
[{'name': 'a', 'state': 'running'}, {'name': 'b', 'state': 'stopped'}, {'name': 'c', 'state': 'running'}]

Now you have the same structure as before, so you can add [?state=='running'].name to it. Do put the above expression into parentheses, you want it to apply to the array output of the wildcard, not to each individual value in the machines mapping:

(machines.*)[?state=='running'].name

or use a pipe expression:

machines.* | [?state=='running'].name

Both give you the desired output:

>>> jmespath.search("(machines.*)[?state=='running'].name", q)
['a', 'c']
>>> jmespath.search("machines.* | [?state=='running'].name", q)
['a', 'c']