Joce
Joce

Reputation: 2332

jmespath: how to search a dict of dict structure

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?

Upvotes: 1

Views: 2692

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121476

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']

Upvotes: 2

Related Questions