Home > Software engineering >  How to get key and value instead of only value when filtering with JMESPath?
How to get key and value instead of only value when filtering with JMESPath?

Time:01-30

Input data:

s = {'111': {'name': 'john', 'exp': '1'}, '222': {'name': 'mia', 'exp': '1'}}

Code:

import jmespath
jmespath.search("(*)[?name=='john']", s)

Output:

[{'name': 'john', 'exp': '1'}]

Output I want:

[{'111': {'name': 'john', 'exp': '1'}}]

CodePudding user response:

Convert the dictionary to the list

l1 = [{'key': k, 'value': v} for k, v in s.items()]

gives

[{'key': '111', 'value': {'name': 'john', 'exp': '1'}}, {'key': '222', 'value': {'name': 'mia', 'exp': '1'}}]

Select the values where the attribute name is john

l2 = jmespath.search('[?value.name == `john`]', l1)

gives

[{'key': '111', 'value': {'name': 'john', 'exp': '1'}}]

Convert the list back to the dictionary

s2 = dict([[i['key'], i['value']] for i in l2])

gives the expected result

{'111': {'name': 'john', 'exp': '1'}}

Example of complete code for testing

#!/usr/bin/python3
import jmespath


s = {'111': {'name': 'john', 'exp': '1'},
     '222': {'name': 'mia', 'exp': '1'}}
#    '333': {'name': 'john', 'exp': '1'}}
l1 = [{'key': k, 'value': v} for k, v in s.items()]
print(l1)
l2 = jmespath.search('[?value.name == `john`]', l1)
print(l2)
s2 = dict([[i['key'], i['value']] for i in l2])
print(s2)

CodePudding user response:

Since you cannot preserve keys in JMESPath when doing an object projection, and that you will have to resort to a loop to have a JSON structure that will allow you to have your desired output see the other answer, the best will probably be to let JMESPath aside for your use case and achieve it with a list comprehension:

Given:

s = {
    '111': {'name': 'john', 'exp': '1'}, 
    '222': {'name': 'mia', 'exp': '1'},
}

print([
    {key: value} 
    for key, value in s.items() 
    if value['name'] == 'john'
])

This yields the expect:

[{'111': {'name': 'john', 'exp': '1'}}]
  • Related