Ted Habermann
Ted Habermann

Reputation: 331

Using the OR operator (|) in jsonpath-ng python

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

Answers (4)

MxR
MxR

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

jjmurre
jjmurre

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

Vikram Kothekar
Vikram Kothekar

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

hanna
hanna

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

Related Questions