Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keys with special characters can't be referenced in filters #3485

Open
lesderid opened this issue Jan 27, 2025 · 3 comments
Open

Keys with special characters can't be referenced in filters #3485

lesderid opened this issue Jan 27, 2025 · 3 comments

Comments

@lesderid
Copy link

If an object key contains special characters (e.g. - or .), it can't be filtered on even though it's a valid JSON object key.

For example, ?has_stuff.foo-bar=true can't be used to check if "foo-bar" is a field of "stuff". There doesn't seem to be any way to escape special characters either.

@leplatrem
Copy link
Contributor

Indeed!

How do you think we could solve this? Using quotes I guess? ?has_stuff."foo-bar"=true?

@lesderid
Copy link
Author

lesderid commented Jan 27, 2025

How do you think we could solve this? Using quotes I guess? ?has_stuff."foo-bar"=true?

There seem to be a few options:

Syntax jq JSONPath
.stuff."foo-bar"
.stuff.["foo-bar"]
.stuff["foo-bar"] 1
.stuff['foo-bar']

Edit: For what it's worth, I don't have a particularly strong preference. I think the first one is probably the most intuitive though.

Footnotes

  1. While this works, I can't find it specified in the docs.

@leplatrem
Copy link
Contributor

Thanks for the reference 👌

If we can't have both, I think I would prefer if we would follow a IETF standard.
We could replace the jsonpatch lib we currently use with this one that seems to support both JSONPath and JSONPatch.

The code that handles the querystring filters is here:

operator = getattr(COMPARISON, keyword.upper())

And filters are then implemented in each storage down the line:

if f.operator == COMPARISON.HAS:

# Subfields: ``person.name`` becomes ``data->person->>name``
subfields = filtr.field.split(".")
for j, subfield in enumerate(subfields):

With tests for both:

def test_has_values(self):
self.validated["querystring"] = {"has_sometimes": True}
result = self.resource.plural_get()
values = [item["sometimes"] for item in result["data"]]
assert None in values
self.assertEqual(sorted([v for v in values if v]), ["available", "present"])
def test_has_values_false(self):
self.validated["querystring"] = {"has_sometimes": False}
result = self.resource.plural_get()
values = ["sometimes" in item for item in result["data"]]

self.create_object({"flavor": "pineapple", "author": "null"})
filters = [Filter("author", True, utils.COMPARISON.HAS)]
objects = self.storage.list_all(filters=filters, **self.storage_kw)
self.assertEqual(len(objects), 4)
self.assertEqual(
sorted([r["flavor"] for r in objects]),
["blueberry", "pineapple", "raspberry", "watermelon"],
)
filters = [Filter("author", False, utils.COMPARISON.HAS)]
objects = self.storage.list_all(filters=filters, **self.storage_kw)
self.assertEqual(len(objects), 1)
self.assertEqual(objects[0]["flavor"], "strawberry")

Would you like to try a contribution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants