Reputation: 331
I have a json structure (client_json) that looks like:
client_json = { "data": [ { "attributes": { "creators": [ { "name": "This is a person", "nameType": "Personal", "givenName": "the", "familyName": "person" }, { "name": "This is an organization", "nameType": "Organizational", "givenName": "the", "familyName": "organization" } ] } } ] }
I am trying to use jsonpath-ng 1.4.3 (https://github.com/h2non/jsonpath-ng) to retrieve creator names.
from jsonpath_ng import jsonpath
from jsonpath_ng.ext import parse
These two expressions give the expected results:
[match.value['name'] for match in parse("data[*].attributes.creators[?(@.nameType='Personal')]").find(client_json)]
[match.value['name'] for match in parse("data[*].attributes.creators[?(@.nameType='Organizational')]").find(client_json)]
I am trying to combine them with an or operator and all of these expressions yield parse errors:
parse("data[*].attributes.creators[?(@.nameType == 'Organizational' | @.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational' || @.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational'), ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational') || ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational') | ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType = 'Organizational' | @.nameType = 'Personal')]")
Thanks for the help.
Upvotes: 5
Views: 2734
Reputation: 606
As written at source code documentation implementation is a little bit "shoddy"
class Union(JSONPath):
"""
JSONPath that returns the union of the results of each match.
This is pretty shoddily implemented for now...
So it only works on the same level objects "out-of-the-box", if you want to union complex independent expressions you need to help the parser with expression boundaries - just put parenthesis around your blocks.
E.g. the expression below
[match.value['name'] for match in
parse("(data[*].attributes.creators[?(@.nameType == 'Organizational')]) | (data[*].attributes.creators[?(@.nameType == 'Personal')])").find(client_json)]
should return both values
['This is an organization', 'This is a person']
Upvotes: 0
Reputation: 432
I bumped into this same problem. I got success using the regex option. Your expression would then become:
parse("data[*].attributes.creators[?(@.nameType =~ 'Organizational|Personal')]")
Upvotes: 3
Reputation: 21
In jsonpath we can apply filter for 'and' condition.
There is no such provision for 'or' condition.
This is what I have came to conclusion after trying lots of ways to implement it.
Upvotes: 2
Reputation: 655
According to the rule jsonpath1 |
jsonpath2, this one goes without error:
[match.value['name'] for match in
parse("data[*].attributes.creators[?(@.nameType == 'Organizational')] | data[*].attributes.creators[?(@.nameType == 'Personal')]").find(client_json)]
however returns only the second name of the two, i.e.
['This is a person']
contrary to what https://github.com/h2non/jsonpath-ng says, that it should return a union.
Upvotes: 0