diff --git a/docs/query.md b/docs/query.md index 6033850..51f0f82 100644 --- a/docs/query.md +++ b/docs/query.md @@ -24,6 +24,23 @@ for value in values: # ... ``` +`Query` objects are iterable and can only be iterated once. Pass the query to `list()` (or other sequence) to get a list of results that can be iterated multiple times or otherwise manipulated. + +```python +from jsonpath import query + +# data = ... + +values = list( + query("$.some[?@.thing]", data) + .skip(5) + .limit(10) + .values() +) + +print(values[1]) +``` + ## Chainable methods The following `Query` methods all return `self` (the same `Query` instance), so method calls can be chained to further manipulate the underlying iterator. diff --git a/jsonpath/fluent_api.py b/jsonpath/fluent_api.py index 599ce68..439c81c 100644 --- a/jsonpath/fluent_api.py +++ b/jsonpath/fluent_api.py @@ -11,6 +11,7 @@ if TYPE_CHECKING: from jsonpath import JSONPathMatch + from jsonpath import JSONPointer class Query: @@ -123,14 +124,16 @@ def values(self) -> Iterable[object]: return (m.obj for m in self._it) def locations(self) -> Iterable[str]: - """Return an iterable of normalized paths for each match.""" + """Return an iterable of normalized paths, one for each match.""" return (m.path for m in self._it) def items(self) -> Iterable[Tuple[str, object]]: - """Return an iterable of (object, normalized path) tuples for each match.""" + """Return an iterable of (object, path) tuples, one for each match.""" return ((m.path, m.obj) for m in self._it) - # TODO: def pointers + def pointers(self) -> Iterable[JSONPointer]: + """Return an iterable of JSONPointers, one for each match.""" + return (m.pointer() for m in self._it) def first_one(self) -> Optional[JSONPathMatch]: """Return the first `JSONPathMatch` or `None` if there were no matches.""" diff --git a/tests/test_fluent_api.py b/tests/test_fluent_api.py index bebe715..701703e 100644 --- a/tests/test_fluent_api.py +++ b/tests/test_fluent_api.py @@ -2,6 +2,7 @@ import pytest from jsonpath import JSONPathMatch +from jsonpath import JSONPointer from jsonpath import query @@ -240,3 +241,10 @@ def test_query_tee() -> None: rv2 = it2.skip(2).one() assert rv2 is not None assert rv2.value == 2 # noqa: PLR2004 + + +def test_query_pointers() -> None: + """Test that we can get pointers from a query.""" + pointers = list(query("$.some.*", {"some": [0, 1, 2, 3]}).pointers()) + assert len(pointers) == 4 # noqa: PLR2004 + assert pointers[0] == JSONPointer("/some/0")