pythonjsonjmespath

JMESPath return records based sublist of dictionaries


I'd like to select elements from a list based on the value of bar in the params key-value pair. See example below.

I have the following code:

with open('foobar.json', 'r') as fp:
    data = json.load(fp)
expr = '[].record'
records = jmespath.search(expr, data)

And the following input file (foobar.json)

[   {   'record': {   'name': 'foobar1',
                      'params': [   {'name': 'foo', 'text': '4'},
                                    {'name': 'bar', 'text': '12'}]}},
    {   'record': {   'name': 'foobar2',
                      'params': [   {'name': 'foo', 'text': '4'},
                                    {'name': 'bar', 'text': '16'}]}}]

The JMESPath query returns both records, as expected.

[   {   'name': 'foobar1',
        'params': [   {'name': 'foo', 'text': '4'},
                      {'name': 'bar', 'text': '12'}]},
    {   'name': 'foobar2',
        'params': [   {'name': 'foo', 'text': '4'},
                      {'name': 'bar', 'text': '16'}]}]

I'd like a JMESPath expression that would return only this one record because the text of the entry in params with name bar is greater than or equal to 13.

[   {   'name': 'foobar2',
        'params': [   {'name': 'foo', 'text': '4'},
                      {'name': 'bar', 'text': '16'}]}]

Solution

  • There is nothing blocking you to make n-levels filter projections in JMESPath.
    So, here, what you are looking for is all element where you will filter the record.params array (first level filter projection) where its elements contains a text greater or equal than thirteen and the name is bar (second level filter projection).

    Which will translate in the query

    [?record.params[?to_number(text) >= `13` && name == `bar`]].record
    

    You just. have to feed this in your expr variable to get your desired result.