Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Python jsonpath_ng filter and other extended features?

Tags:

json

jsonpath

I'm trying different ways of extracting useful information from JSON with Python. I tried both jsonpath_rw_ext and jsonpath_ng. Now I'm able to use jsonpath_rw_ext but jsonpath_ng doesn't work. I don't want to just give up jsonpath_ng for I may didn't use it in a correct way. Check the following code:

import jsonpath_rw_ext
from jsonpath_ng.ext import parse
import json
from pprint import pprint


json_str = '''{
    "students": [
        {"name": "Peter", "gender": "Male", "age": 20},
        {"name": "Mary", "gender": "Female", "age": 30},
        {"name": "Susan", "gender": "Female", "age": 40}
    ],
    "teachers": [
        {"name": "William", "gender": "Male", "age": 30},
        {"name": "John", "gender": "Male", "age": 40},
        {"name": "Lucy", "gender": "Female", "age": 50}
    ]
}'''

json_obj = json.loads(json_str)
print 'jsonpath_rw_ext:'
female_students = jsonpath_rw_ext.match('$.students[?gender=="Female"]', json_obj)
pprint(female_students)
print 'jsonpath_ng:'
female_students = parse('$.students[?gender=="Female"]').find(json_obj)
pprint(female_students)

The jsonpath_rw_ext part outputs the following result, with is normal: jsonpath_rw_ext:

[{u'age': 30, u'gender': u'Female', u'name': u'Mary'},
 {u'age': 40, u'gender': u'Female', u'name': u'Susan'}]

But jsonpath_ng part outputs the following result, which I cannot understand. Is there any specific reason that jsonpath_ng returns the following result? And how can I get a similar result in a simple way?

Result returned by jsonpath_ng:

[
    DatumInContext(
        value={
            u'gender': u'Female', u'age': 30, u'name': u'Mary'
        }, 
        path=<jsonpath_ng.jsonpath.Index object at 0x000000000315AA90>, 
        context=DatumInContext(
            value=[
                {u'gender': u'Male', u'age': 20, u'name': u'Peter'}, 
                {u'gender': u'Female', u'age': 30, u'name': u'Mary'}, 
                {u'gender': u'Female', u'age': 40, u'name': u'Susan'}
            ], 
            path=Fields('students'), 
        context=DatumInContext(
            value={
                u'students': [
                    {u'gender': u'Male', u'age': 20, u'name': u'Peter'}, 
                    {u'gender': u'Female', u'age': 30, u'name': u'Mary'}, 
                    {u'gender': u'Female', u'age': 40, u'name': u'Susan'}
                ], 
                u'teachers': [
                    {u'gender': u'Male', u'age': 30, u'name': u'William'}, 
                    {u'gender': u'Male', u'age': 40, u'name': u'John'}, 
                    {u'gender': u'Female', u'age': 50, u'name': u'Lucy'}
                ]
            }, 
            path=Root(), 
            context=None
        )
        )
    ),
    DatumInContext(
        value={u'gender': u'Female', u'age': 40, u'name': u'Susan'}, 
        path=<jsonpath_ng.jsonpath.Index object at 0x000000000315ABA8>, 
        context=DatumInContext(
            value=[
                {u'gender': u'Male', u'age': 20, u'name': u'Peter'}, 
                {u'gender': u'Female', u'age': 30, u'name': u'Mary'}, 
                {u'gender': u'Female', u'age': 40, u'name': u'Susan'}
            ], 
            path=Fields('students'), 
            context=DatumInContext(
                value={
                    u'students': [
                        {u'gender': u'Male', u'age': 20, u'name': u'Peter'}, 
                        {u'gender': u'Female', u'age': 30, u'name': u'Mary'}, 
                        {u'gender': u'Female', u'age': 40, u'name': u'Susan'}
                    ], 
                    u'teachers': [
                        {u'gender': u'Male', u'age': 30, u'name': u'William'}, 
                        {u'gender': u'Male', u'age': 40, u'name': u'John'}, 
                        {u'gender': u'Female', u'age': 50, u'name': u'Lucy'}
                    ]
                }, 
                path=Root(), 
                context=None
            )
        )
    )
 ]
like image 211
Vespene Gas Avatar asked May 11 '18 07:05

Vespene Gas


2 Answers

find() method return the list of DatumInContext Objects. So you can use List parsing. For getting the value from DatumInContext you can use its attribute value which will return just the same value as you are getting in response of

jsonpath_rw_ext.match('$.students[?gender=="Female"]', json_obj)

So, instead of using

pprint(female_students)

directly, You can use female_students by parsing list item with its value

pprint([match.value for match in female_students])
like image 167
Shivang Garg Avatar answered Oct 04 '22 02:10

Shivang Garg


For a single line solution using jsonpath_ng, use:

[match.value for match in parse('$.students[?gender=="Female"]').find(json_obj)]

This correctly returns:

[{'name': 'Mary', 'gender': 'Female', 'age': 30},
 {'name': 'Susan', 'gender': 'Female', 'age': 40}]
like image 38
Joelster Avatar answered Oct 04 '22 02:10

Joelster